(navigation image)
Home American Libraries | Canadian Libraries | Universal Library | Community Texts | Project Gutenberg | Children's Library | Biodiversity Heritage Library | Additional Collections
Search: Advanced Search
Anonymous User (login or join us)
Upload
See other formats

Full text of "Io programmo 90"

ANZICHÉ 



IMPERDIBILE! 4,90 P"o 

ISirS nu«Sn MISE "T'eURO ^'eur-O 



SOLO PIO QUESTO MESE 



ROGRAMMO 



PER ESPERTI E PRINCIPIANTI 





JAVA! 



[ CREA APPLICAZIONI CHE RICONOSCONO 
\ LA VOCE ED ESEGUONO 
I I TUOI ORDINI 

■ Integra un motore 
di riconoscimento vocale 
nel tuo codice 



mrwidth o± ree 

lnf'HelcjIit. of rei 

ntln["Ai-ea o± rect 



Dai in pasto un dizionario 
al tuo sofware 



Inizia subito 
usando gli esempi 




LO- 



iCD 

IO 
IO 

iO) 

5Lp 

500 
SCM 



PHP MULTILIIUGUA 

Pronti per i nuovi mercati. Scrivi applicazioni 
Web che si adattano al paese di chi li visita!!! 

HACKING VISUAL BASIC 

Incredibile! ti sveliamo le funzioni 
non documentate della shell 






.NET 



gin 



EDIZIONI 

MASTER 

www.edmaster.lt 



MS DATABASE 
APPLICATION BLOCK 

Programma velocemente 
utilizzando i blocchi di codice 
elaborati da Microsoft 



WINDOWS 
UPDATE AGEIUT 

Scopri II nuovo SDK per avere 
il controllo completo sugli 
aggiornamenti di sistema 



odicità mensile • APRILE 2005 • ANNO IX, N. 



AL VIA IL CORSO 



'à^lLl 



} 



I primi passi per imparare 
a programmare i cellulari 



VB .NET E LA GRAFICA 



CAMBIARE MENU 

Operare nel cuore delle 
interfacce per renderle 
più accattivanti 



DATABASE 



TUTTI I SEGRETI 
DI ADO.NET 

Programmi veloci come 
fulmini, sfruttando al massimo 
le tecnologie di Microsoft 

C# INCONTRA 
MYSQL 

Scopri le transazioni: 
per ottimizzare l'accesso 
concorrente ai database 



IOPROGRAMMO WEB 



RETE BLINDATA 
CONSTRUTS!!! 

Come usare il framework 
Java che rende inattacabili 
i tuoi siti web 



TECNICA 



APPLICAZIONI CHE 
FANNO PER TRE!! 

Usare i Java thread per fare 
più cose insieme senza 
perdere velocità 

FILTRI BAYESIANI 

Ecco come fanno gli esperti 
a non ricevere la posta 
spazzatura 

- MSICljtT Z0U3 



PM\ 


< — 


^PUNTI 


< 


^PUNTI 


- PUNTI 


^= 






L 90 






IOPL90 



KERNEL Al RAGGI X: ALL'INTERNO 
DEL SISTEMA PER CAPIRNE I SEGRETI 



Questo mese su ioProgrammo 



Anno IX - N.ro 4 (90) - Aprile 2005 - P 

Reg. Trib. di CS al n.ro 593 del 11 Febbraio 1997 
Cod. ISSN 1128-594X 
E-mail: ioprogrammo@edmaster.it 
http://www.edmaster.it/i 

http://www.ioprogrammo.it 



lio, L. Bui 
icchiati, A. Marroccelli, 




parte di tutto ciò che facciamo e di ogni decisione che prendiamo 



miglioramento delle performance ambientali e sulla prevenzione 



^, i& Certificato UNI EN ISO 14001 
§g31l§FN.9191CRMT 

Realizzazione Multimediale: SET S.r.l. 



Realizzazione CD-Rom: Paolo lacona 

Pubblicità: Master Advertising s.r.l. 

lArib 
Tel. 02 831212 - Fax 02 83121207 



Sales Director: Max Scortegagna 



Tel. 02 831212 - Fax 02 83121206 



nministratore Delegato: Massimo Sesti 

ABBONAMENTO E ARRETRATI 
ITALIA: Abbonamento Annuale: ioProgrammo Basic (11 numeri) 
€52,90 sconto 30% sul prezzo di copertina di €75,90 ioProgrammo 
con Libro (11 numeri + libro) €76,00 sconto 30% sul prezzo di 
copertina di €108,90 



Costo arretrati (a copia): il doppio del prezzo di copertina + € 5.32 
spese (spedizione con corriere). Prima di inviare i pagamenti, 
verificare la disponibilità delle copie arretrate allo 02 831212. 



dovrà essere inviata via fax allo 02 83121206, oppure via posta a EDI- 
ZIONI MASTER via Ariberto, 24 - 20123 Milano, dopo av 
il pagamento, secondo le modalità di seguito elencate: 

• cc/p n.16821878 o vaglia postale (inviando copia della ricevuta del 
---■- "ti); 

• assegno bancario non trasferibile (da inviarsi in busta chiusa insieme 



mmmmmm 



la Vs. sottoscrizione insieme alla richiesta). 

li Master S.pA c/o Banca Cred 
S.p.a. c/c 01 000 000 5000 ABI 03032 CAB 80880 CIN Q (inviando copia 



SI PREGA DI UTILIZZARE IL MODULO RICHIESTA ABBONAMENTO POSTO 
NELLE PAGINE INTERNE DELLA RIVISTA. L'abbonamento verrà attivato sul 



Sostituzioni: Inviare il CD-Rom difettoso in busta chiusa a: 
~ >ter Servizio Clienti - Via Ariberto, 24 - 20123 Milano 



02 831212 

servizioabbonati@edmaster.it 

' " """ira, 2/6 - Ariccia (Rom 
Stampa CD-Rom: Neotek S.r.l.- C.da Imperatore - zona ASI 
Bisignano (CS) 
Distributore esclusivo per l'Italia: Parrini & C S.pA 



Edizioni Master edita: Computer Bild, Idea Web, 
GolOnLine I 
DVD Magazine, Office Magazine, La mia Barca, ioProgra 



mSmmmmm 



MPC, Disc 

I Fantastici CD-Rom, PC VideoGuide, I Corsi di Win Magazine, 
I Filmissimi in DVD, La mia videoteca, TV e Satellite, Win Extra, 
Home entertainment, Digital japan, Digital Music, Horror Mania, 



|£É ITpartM\ 

L ] <* KJo^ J L' Universo Tee 



T Piccoli particolari 

È incredibile la quantità di email che giun- 
gono giornalmente in redazione da parte 
di persone che si avvicinano per la prima 
volta alla programmazione. Qualche san- 
tone delle statistiche aveva tuonato qual- 
che tempo fa: "non si fa programmazione 
in Italia". Forse, avrà avuto il suo bravo 
elenco di numeri da analizzare per affer- 
mare qualcosa del genere. Invece noi che 
in mezzo alla programmazione ci siamo 
tutti i giorni, avvertiamo un entusiasmo 
tangibile, presente, forte, in questo seg- 
mento che così tanto ci attrae. Mi sono 
sempre chiesto cosa potesse stimolarmi a 
tuffarmi in un universo complesso quale è 
quello fatto di codice, algoritmi, numeri, 
ragionamento. Mi sono risposto spesso e 
volentieri, forse peccando di presunzione, 
che quello che mi rende totalmente avvol- 
to al mondo dello sviluppo è la possibilità 
di creare qualcosa. Un prodotto, un 
software, nasce da un'idea, viene svilup- 
pato secondo una forma che per certi 
versi è simile all'arte, viene affinato e coc- 
colato come il più sentito dei capolavori. 



Con questo non voglio assimilare il nostro 
lavoro alla genialità immortale degli arti- 
sti, non arrivo a tali vette di presunzione, 
ma è anche vero che sentire di essere 
capace di produrre qualcosa che aiuta a 
migliorare in un qualche modo la qualità 
della vita di questo nostro mondo, è pro- 
prio quello che mi tiene avvinto alla com- 
plessità della sfida con la programmazio- 
ne. È che il software aiuti a migliorare la 
qualità della vita è innegabile, guardatevi 
intorno, in tutto o quasi tutto quello che vi 
circonda c'è dentro almeno una riga di 
codice, e se non c'è, sicuramente qualche 
riga di codice sarà stata spesa per produr- 
re l'oggetto in questione. Perciò il mio 
invito è quello di "darci dentro". Nuovi 
programmatori, non fermatevi davanti alle 
difficoltà, qualcosa potrebbe apparirvi 
complesso, non tutto vi sarà chiaro, ma è 
proprio il fascino di questa sfida, la 
volontà di conoscere al fine di creare che 
ci consente di dire con orgoglio di far 
parte del mondo dello sviluppo! 

Fabio Farnesi 



Q CD Q WEB 

nome_file.zip 



w M 



All'inizio di ogni articolo, troverete un simbolo che indicherà la presenza di 

codice e/o software allegato, che saranno presenti sia sul CD (nella posizione 

di sempre \soft\codice\ e \soft\tools\) sia sul Web, all'indirizzo 

http://cdrom.ioprogrammo.it. 

Per scaricare software e codice da Internet, ogni mese indicheremo una 

password differente. Per il numero che avete fra le mani la combinazione è: 

Username: gatto Password: matita 



PAROLA 
DI JAVA! 

Creare applicazioni 
che riconoscono 
la voce e ri 
la cosa giusta 



pag. 16 




■ Il motore di riconoscimento 
vocale Sphinx4 

Definire le grammatiche 

Riconoscere i comandi 



Questo mese su ioProgrammo 



HACKING VISUAL BASIC 



Ti sveliamo le funzioni non documentate della shell 



pag. 66 



SISTEMA 



Sistema sempre aggiornato. . pag. 38 

Windows Update Agent Ì'SDK di Microsoft per 
gii aggiornamenti 



GRAFICA 



Oggi cambiamo menu! pag. 42 

Impariamo come strutturare al massimo il fra- 
mework .NET per realizzare menu estrema- 
mente personalizzati e con grafica accattivante 



SCRIPTING 



LUA: il linguaggio del software pag. 46 

Aggiuungere un interprete di comandi 
al software 



DATABASE 



Meno codice per tutti! pag. 50 

Utilizzare le classi Data della libreria 
Application Blocks fornita da Microsoft 

Transazioni Con c# e MySql . . pag. 57 

Cosa sono e a cosa servono e come sfruttarle in 
MySQL e in C# 

Accesso ai DB con 

Visual Basic .Net 2003 pag. 60 

Come salvare, cancellare e modificare i dati 
Poche semplici regole 



VISUAL BASIC 



Il calendario di un campionato 

di calcio pag. 72 

Le routine che interrogano un documento e un 
database in formato XML 



BACKSTAGE 



Filtri bayesiani contro la posta 
spazzatura pag. 77 

/ principali sistemi di protezione, per 
proteggersi dalle email indesiderate. 
Implementare un filtro Bayesiano 



RUBRICHE 



Gli allegati di ioProgrammo 

// software in allegato alla rivista 



pag. 6 



News pag. 8 

le più importanti novità del mondo della program- 



mazione 



La posta dei lettori 

L'esperto risponde ai vostri quesiti 



pag. 10 



Il meglio dei newsgroup pag. 12 

^ioProgrammo raccoglie per voi le discussioni 



SECURITY 



Hacker semaforo rosso pag. 82 

Come prevenire gli attacchi di tipo Denial of 
Service 



ELETTRONICA 



Mettiamo la mappa nel GPS . pag. 86 

Disegniamo la traccia degli spostamenti su una 
mappa 



CORSI 



ASP • Data Controls e l'accesso 

ai dati pag. 90 

Sfruttare ADO.NET per siti web che fanno uso 
di database 

Flash ActionScript • Ereditarietà in 
ActionScript pag. 92 

Come estendere le classi di ActionScript 

Visual Basic.NET • Come frazionare un 
programma pag. 99 

Le procedure, le piccole unità logiche di codice 
che, unite, formano un'applicazione più ampia. 

Javascript • Le basi pag. 104 

Indispensabile per progettare pagine Web 



SOLUZIONI 



Il Kernel ai raggi X pag. 126 

Impariamo come il tempo viene diviso fra le 
varie applicazioni 



IOPROGRAMMO WEB 



PHP MULTILINGUA pag. 22 

Pronti per i nuovi mercati. 
Applicazioni che si adattano 
al paese di chi li visita 

RETE BLINDATA 
CON STRUTS 

Come usare il 
framework Java 
che rende 
inattaccabili 
le tue 
applicazioni 



THREAD E BLOCCHI 
CRITICI pag. 32 

La breve serie che inizia questo 
mese spiega come si usano i thread 
nei programmi Java 




CORSO SIMBYAN 



I PRIMI PASSI 



A ROGRAMMARE 
I CELLULARI pag. 57 




più interessanti della rete 

Tips & Tricks pag. 112 

Trucchi per risolvere i problemi più comuni 

Express pag. 114 

le guide passo passo per realizzare applicazioni 
senza problemi 

Software pag. 118 

/ contenuti del CD allegato ad ioProgrammo. 
Corredati spesso di tutorial e guida all'uso 



I [ http://forum.ioprogrammo.it 



QUALCHE CONSIGLIO UTILE 



I nostri articoli si sforzano di essere 

comprensibili a tutti coloro che ci 

seguono. Nel caso in cui abbiate 

difficoltà nel comprendere esattamente 

il senso di una spiegazione tecnica, è 

utile aprire il codice allegato 

all'articolo e seguire passo passo 

quanto viene spiegato tenendo 

d'occhio l'intero progetto. Spesso per 

questioni di spazio non possiamo 
inserire il codice nella sua interezza nel 

corpo dell'articolo. Ci limitiamo a 

inserire le parti necessarie alla stretta 

comprensione della tecnica. 



ioProgrammo cerca articolisti freelance 1 
competenti nei seguenti argomenti: 

Javascript, Python, Perl, 

ASP.NET, PHP, Flash, 

Security 

Inviare curriculum dettagliato a 
ioProgrammo@edmaster.it 



Gli allegati di ioProgrammo 



I contenuti del CD-Rom 



Dev C++ 5 Beta 9 

Un editor C++ a basso costo 




Apache 1.3.33/2.0.52 

Directory: /Apache/ 

Tomcat 5.5.4 

Il servlet container per Java e JSP 

Directory: /tomcat 

PHP 5.0.3 

Il linguaggio di scripting per il web 

Directory: /PHP 



Python 2.4 

Un linguaggio orientato agli oggetti 
con tanto di supporto a classi ed ere- 
ditarietà 

Directory: /Python 

Hibetnate 3.0 

Il framework per gestire la persisten- 
za dei dati 

Directory /H ibernate 



MySQL 4.1.9 

Il server di database OpenSource più 
diffuso al mondo 

Directory /Mysql 

MySQL Administrator 

Il front-end per amministrare mysql in 
modo grafico 

Directory: /mysql-administrator 

MyODBC 

Il connector universale per MySQL 

Directory: /MyODBC 



MySQL Query Browser 

L'editor SQL per MySQL 

Directory: /mysql -query- browser 



Sqlite 2.8.15 

Il nuovo database Bundled con PHP5 

Directory: /Sqlite 

HSqldb 1.7.3 

Un database piuttosto potente 

Directory /hsqldb 

SharpOevelop 1.0.3.1761 

L'alternativa a Visual Studio a basso 
costo 

Directory: /Sharpdevelop 

Aqua Data Studio 4.0 

Il query builder leggero ed efficiente, 
quasi un indispensabile 

Directory /Acquadatastudio 

Blender2.36 

Un modeller per oggetti 3D. Molto 
simile a 3D Studio 




Directory: /Blender3D 



Il software del mese 



Ultimate++ 

Un fantastico ide "quasi RAD" 
per le applicazioni C++ 

Si tratta di un ambiente di svi- 
luppo per applicazioni C++, 
nella versione allegata a 
ioProgrammo lo trovate abbi- 
nato al compilatore Mingw, 
nonostante questo può essere 
utilizzato anche con altri com- 
pilatori. 

L'ambiente offre tutte le carat- 
teristiche classiche di un 
ambiente professionale, parlia- 
mo di code complexion, 
debugging, sintax highligh- 
ting. 

La caratteristica più interes- 
sante dell'IDE è che è dotato di 
un minimo di funzionalità RAD 
il che dato i bassi costi del pac- 
chetto lo rende particolarmen- 
te attraente agli occhi degli 
sviluppatori. 



I 



13 



v: 



Directory: /Ultimate 



[pag.116] 



BORLAND JBUILDER 2005 
FOUNDATION EDITION 

L'eccezionale ambiente di Borland per lo sviluppo Java 



Jbuilder è l'ambiente proposto da 
Borland per lo sviluppo di applicazioni 
Java. Come è tradizione di Borland si trat- 
ta di un ambiente incredibilmente curato 
nei particolari. Dotato di tutte le caratte- 
ristiche essenziali di un ottimo editor 
Java, la versione Foundation ha dalla sua 
parte il costo praticamente nullo, dovuto 
alla sua licenza, l'uso della foundation è 
infatti gratuito per usi personali. Certo ha 
delle limitazioni rispetto alla versione 
enterprise, ad esempio non è possibile 
gestire i progetti UML, ma si tratta di 
limitazioni che comunque influiscono solo 
sulla produzione di progetti di largo 
respiro. Insomma per un programmatore 
Java che si accinge a iniziare e che non ha 
necessità di sviluppare progetti Enterpri- 




se, la versione Foundation è assoluta- 
mente da provare. 





Nello spirito tipico degli ambienti prodot- 
ti da Borland, anche JBuilder é un tool 
che segue la filosofia che le applicazioni 
vanno disegnate e che la produttività di 
un programmatore dipende anche da 
quanto tempo riesce a risparmiare nel 
disegno dell'Interfaccia, pertanto JBuilder 
é dotato di un Visual Designer che con- 
sente di disegnare le form per trascina- 
mento dei componenti. Solo vantaggi per 
JBuilder, unico punto a sfavore é che 
richiede un sistema sufficientemente do- 
tato per potere essere utilizzato con pro- 
fitto 
Directory /JbuilderFoundation [pag.1 1 5] 



Lazarus 0.9.4 

Un ambiente RAB più copi latore 
Freeware per object Pascal 

Volevate imparare a programma- 
re in Delphi ma non avevate la 
possibilità di comperare il costoso 
ambiente di casa Borland? 
Lazarus è ciò che fa per voi. Si 
tratta di un clone Freeware del 
noto Delphi. La somiglianza è 
incredibile! Il modo di procedere 
altrettanto! Lazarus è un RAD 
funziona con la stessa logica di 
Delphi, supporta la VCL, è dotato 
di tutti i componenti classici di 
Delphi, è sufficientemente veloce 
e affidabile. Certo, non è il 
Borland Delphi 2005 con tutte le 
sue infinite possibilità, ma rap- 
presenta un'ottima base per chi 
vuole sviluppare applicazioni 
Standalone utilizzando la produt- 
tività classica di un ambiente RAD 



Directory /Lazarus 



[pag.115] 



* 6 /Aprile 2005 



http://www.ioprogrammo.it 



Gli allegati di ioProgrammo 



I Kit del programmatore 

Gli strumenti essenziali sia per il professionista 
sia per chi vuole cominciare 




PHP 5.0.3 

L'ultima versione 
del linguaggio 



2.0.9 

Uno degli editor 
per PHP più amati 
dai programmatori 



DEV C++ 5 
BETA 9 

Lo standard di cui 
non puoi fare a meno 

ULTIMATE 

C++ 

Nuovissimo 

ed addirittura RAD 





SHARP 
DEVELOP 

1.0.3.1761 

L'alternativa a Visual 
Studio a basso costo. 
Programma in .NET 
in modo rapido e 
visuale 



LAZARUS 

0.9.4 

Un ambiente RAD, 

più un copilatore 

Freeware per object 

Pascal. 

Quasi come Delphi 

ma gratis! 





1.5.0 

Indispensabile 
per programmare 
in JAVA 

ECLIPSE 3.0.1 

La piattaforma 
universale 




Dev-PHP 2.0.9 

Ottimo editor PHP OpenSoutce 

Se state iniziando a sviluppare 
in PHP avrete bisogno di un edi- 
tor. Scrivere codice con il note- 
pad può essere un esercizio 
divertente, ma quando iniziate 
a scrivere script leggermente 
più complessi si impone la scel- 
ta di passare a un editor più 
completo. DEV-PHP non solo è 
completo ma anche molto 
potente. 

Dotato di code completion, sin- 
tax highlighting, funzionalità di 
ricerca avanzate ed una serie di 
tool piuttosto interessanti rap- 
presenta una grande scelta per 
programmare in PHP. Inoltre è 
un editor straordinariamente 
leggero, oltre che gratuito ed 
OpenSource. In molti lo trove- 
ranno molto comodo. 
Da non perdere! 




Directory: /DevPHP 



[pag.116] 



Spe 0.7.0 

Un editor evoluto per Python 

Directory: /Spe 

Eclipse 3.0.1 

La piattaforma universale multifun- 
zione 

Directory: /Eclipse 

Pione 2.0 

Un cms atipico 




Directory /Pione 

lrrlichtO.7 

Sviluppare Giochi 3D potenti in modo 
semplice 

Directory: /irrlicht 

Smarty 2.6.7 

Il template engine per PHP 

Directory /Smarty 

Sqlite .NET 

Un connector .NET per questo interes- 
sante database 

Directory: /Sqlite 

Menalto Gallery 2.0 

Una completa gallery fotografica 



pronta per essere usata sul Web 

Directory: /gallery 



TikiWiki 

Un Wiki piuttosto interessante 

Directory /tikiwiki 

CseHTML Validator Lite V6.52 

Un validatore per le vostre pagine 
html 



0"^^^'"'""°^" 


pr;..— 


;|:JF ! 


LE TEST 




'PSjr 1 -- 1 — 









Directory /csevalidator 

MySQL Connector 

Per utilizzare MySQL direttamente da 
applicazioni .NET, Java, Python 

Directory: /Connector 

Sphinx4 

Il motore di riconoscimento vocale 

Directory: /Sphinx4 

Lua 

Per dotare i propri programmi di un 
ambiente di scripting 

Directory: /Lua 

PHP-GTK 

Creare GUI con PHP 

Directory: /PHP-GTK 



Tortoise CVS 

Ottimo tool per il controllo della revi- 
sione 

Directory: /tortoisecvs 



Integra JMS in applicazioni PHP 

mantaray_1 .2. 1_bin.zip 



Prova subito 



DAMN SMALL 
LINUX 

Linux in 50 MB: una 
delle distribuzioni più 
piccole al mondo 

Masterizza la traccia ISO, 
inserisci il CD e goditi 
rebrezza del pinguino. 




http://www.ioprogrammo.it 



Aprile 2005/7 ► 



NEWS T 






ini ARRIVO 
IL CELLULARE 

coni Linux 

irettamente dalla Germa- 
'nia e precisamente da 
Road GMBH è in arrivo un 
prodotto molto simile al co- 
nosciutissimo Nokia Commu- 
nicator ma basato su Linux e 
addirittura su un sufficien- 
temente recente kernel 2.6. Il 
prodotto integrerebbe GSM, 
GPRS, IrDA, Bluetooth, 
WLAN, tutte le applicazioni 
tipiche come un browser per 
Internet, un client Email un 
Viewer per MS Word e per 
Excel, il classico PIM e tutte le 
applicazioni più comune- 
mente usate. L'interfaccia 
grafica sarebbe però basata 
su Qtopia mentre il cuore sa- 
rebbe il noto Linux con Ker- 
nel 2.6. Il prodotto porta la 
sigla di S101 e sono previste 
versioni basate anche su 
Symbian e su Windows CE. 

È ACCORDO 
FRA IBM 
E ZENO 

e strade dell'informatica 
i! Cosa hanno 
in comune Big Blue, colosso 
dell'informatica aziendale e 
Zend leader degli strumenti 
di sviluppo per PHP? Fino a 
ieri niente. Da oggi hanno in 
comune un accordo per svi- 
luppare insieme strumenti 
per aiutare gli sviluppatori a 
scrivere applicazioni basate 
sul popolare linguaggio PHP. 
La notizia è di quelle che 
scotta. Il solo PHP rappresen- 
ta il maggior concorrente di 
Microsoft per quanto riguar- 
da lo sviluppo di applicazioni 
Web, l'accordo con Zend rap- 
presenta un muro difficile da 
superare per il colosso di 
Redmond. Inoltre la partner- 
ship di IBM con Zend garanti- 
rà a PHP di occupare fasce di 
mercato che fino ad ora 
aveva soltanto sfiorato, vedi 
il mercato Business /Azien- 
dale. 



CIA LA PRIMA SOLUZIONE 

ITALIANA OPEIUSOURCE 

DI IDEIUTITY MANAGEMENT 



Inutile ricordare quanto e 
come Internet sia cambia- 
ta dalla sua nascita e conti- 
nui ad evolvere con eccezio- 
nale rapidità. Altrettanto ve- 
ro è che cresce l'offerta di 
prodotti legati al mondo In- 
ternet, siano essi servizi o 
prodotti materiali. Allo stes- 
so modo crescono le solu- 
zioni di intranet aziendale 
basate sulle stesse identiche 
metodologie applicate al 
mondo Internet. Se tutto 
questo non può che aiutarci 
a migliorare la qualità della 
vita, d'altra parte è inevitabi- 
le che questo sviluppo sti- 
moli la nascita di ulteriori e 
fin qui sconosciute proble- 
matiche. La gestione delle 
identità delle persone è una 



di queste. Come gestire a 
livello aziendale la registra- 
zione degli utenti? Come 
dialogare con la crescente 
necessità di privacy? Come 
assicurarsi della corretta 
identità degli utenti? E anco- 
ra come sviluppare applica- 
zioni che supportino gli 
utenti nella gestione delle 
loro identità? 

Ad esempio è opportuno svi- 
luppare applicazioni che 
consentano agli utenti di 
cambiare le loro password, i 
loro dati personali senza per 
questo dovere passare attra- 
verso un helpdesk. Tutte 
queste problematiche sono 
generalmente assistite da 
software di Identity Manage- 
ment. Sys-Net è una delle 



aziende Italiane che si è 
maggiormente distinta in 
questo settore e annovera 
clienti di grande livello come 
Banca Intesa, Gruppo San 
Paolo e molti altri ancora. 
Colpisce la volontà di punta- 
re sull'Open Source come 
scelta strategica anche per lo 
sviluppo di soluzioni così 
delicate. 

Eppure Barbara Dell'Era, Di- 
rettore Commerciale della 
Sys-Net si dichiara convinta 
che la direzione intrapresa 
porterà da un lato un enor- 
me sviluppo tecnologico del 
progetto, dall'altra una cre- 
scente possibilità di custo- 
mizzazione della soluzione. 
Noi, ovviamente siamo d'ac- 
cordo con lei. 



BEN GOODGER ABBANDONA 
FIREFOX E PASSA A GOOGLE 



"i: 



stata un'esperienza ente 
i ressante, emozio 
nante ed educativa... 
tuttavia quando un 
progetto durato molto 
tempo raggiunge un 
suo traguardo essen- 
ziale è normale che la 
gente che vi ha lavo- 
rato prenda una pau- 
sa di riflessione , si 
guardi intorno e deci 
da cosa vuole fare" . 
Questo si legge sul Blog di 
Ben Goodger, direttore ese 
cutivo del gruppo che ha portato 
alla nascita di FireFox il più temibile 
rivale di Internet Explorer http://weblogs 
. mozillazine. org/ben/archives/OO 7366.html 
. Segue l'annuncio di essere stato ingag- 
giato dal noto Google. Al momento Good- 
ger è stato evasivo sul ruolo che avrà all'in- 
terno di Google, viceversa è emerso chia- 



ramente che nonostante il 
suo impegno in Google 
continuerà a lavorare 
ancora nel gruppo 
che ha portato 
all'avvento di 
Firefox 1.0 al- 
meno fino al 
rilascio della 
versione 2.0 
passando attra- 
verso la 1.5. 
Certo è che la noti- 
zia è di quelle che la- 
sciano senza fiato, non 
si sa cosa potrebbe partori- 
re dai genietti che hanno fatto 
nascere il più importante motore di ricer- 
ca al mondo e dalla fantasia del capo pro- 
getto di FireFox. A nostro avviso possono 
nascere solo guai per Microsoft, ma questa 
è solo una nostra sensazione. 
Staremo a vedere. 




* 8 /Aprile 2005 



http://www.ioprogrammo.it 



NEWS T 



IMO Al BREVETTI 
SUL SOFTWARE 

Da qualche tempo ormai ci portiamo 
dietro la diatriba che contrappone 
TUnione Europea alle associazione per 
la promozione del software libero in 
materia di brevettabilità del software. 
Per il momento sembra avere avuto 
ancora una volta ragione il movimento 
che si oppone al testo di legge sulla bre- 
vettabilità. 

Di fatto il parlamento europeo avrebbe 
azzerato, grazie alle numerose mozioni 
arrivate un pò da tutti i paesi europei, 
l'attuale proposta. 

Si dovrà dunque ricominciare da zero, 
tenendo questa volta conto delle obie- 
zioni mosse da chi ritiene che il softwa- 
re sia un bene troppo prezioso e troppo 
utile all'umanità perché lo sviluppo 
possa essere fermato da lacci e lacciuoli 
burocratici. Il sito di riferimento per 
comprendere le ragioni di chi si oppone 
alla brevettabilità del software è http:// 
www. nosoftwarepatents. com/it/m/intro 
/index. html 



RFID FUORI DALLA 
SCUOLA ELEMENTARE 



Una scuola Elementare in 
California aveva avviato un 
esperimento per dotare gli alunni 
di un Badge connesso a un Rfid. 
Lo scopo era ovviamente quello 
di tenere sotto controllo gli 
spostamenti degli alunni e di 
automatizzare alcuni processi 
interni. Immediatamente dopo 
l'attuazione del provvedimento 
era montata la protesta dei 
genitori che lamentavano una 
violazione della privacy nei 
confronti dei loro ragazzi. Il 
preside era stato costretto ad 
eliminare i sensori che leggevano 
le informazioni provenienti dagli 
RFID dalle porte dei bagni dove 
erano stati montati per 
mantenerli attivi solo nelle porte 
delle aule. Poco dopo 
l'esperimento è stato sospeso ed 



è stato rescisso il contratto 
all'azienda che aveva ottenuto 
l'appalto del progetto 
adducendo la motivazione di 
"scontento" nel come lo sviluppo 
era stato portato avanti. Infine la 
colpa di tutto quello che non 
funziona è sempre dei 
programmatori! 




MOTOROLA VERSO 
IL VOICE OVER IP 

Alcuni di voi forse conosceranno l'annuncio che Motorola, colos 
SkVPe. Non ancora diffusissima Holla tolofnnia mnhilo nrnHiir 



Alcuni di voi forse conosceranno 
Skype. Non ancora diffusissima 
in Italia, conta però nel mondo circa 
25 milioni di utenti registrati. Skype è 
una giovane società che fornisce 
servizi a basso costo di telefonia su 
Internet basati ovviamente sulla 
tecnologia Voice Over IP. 
In Italia ci sono stati fino ad ora diver- 
si tentativi di avviare in modo mas- 
siccio il VolP ma nessuno di questi ha 
realmente fino ad ora riscosso un 
enorme successo. Se le tendenze 
sono quelle di oltreoceano è però 
molto probabile che anche da noi in 
tempi non eccessivamente lunghi 
faranno la loro comparsa servizi affi- 
dabili che consentano di telefonare 
utilizzando Internet e ad un costo 
sicuramente inferiore a quelli attuali. 
Nel frattempo ancora una volta 
oltreoceano desta un certo interesse 



l'annuncio che Motorola, colosso 
della telefonia mobile produrrà 
telefonini Skype Enabled. Al momen- 
to non c'è una vera precisa offerta 
commerciale su come questo possa 
influire sulle abitudini dell'utente 
finale, tuttavia c'è' un accordo per cui 
Motorola produrrà, cuffie e microfoni 
certificati per essere usati con tecno- 
logia VolP e in comarketing con 
Skype. E' curioso mostrare come la 
tecnologia stia evolvendo in questa 
direzione. D'altra parte quello che 
vediamo oggi è solo un germe delle 
tecnologia che saranno da qui a quat- 
tro o cinque anni, d'altra parte il 
primo televisore misurava appena 
nove pollici no? Sicuramente in breve 
tempo le nostre abitudini di vita 
saranno molto cambiate in relazione 
a quelle che al momento sembrano 
soltanto fantasiosi rumors. 



MASCÈ GRUSP 
IL "GRUPPO 
UTENTI E 
SVILUPPATORI 
PHP" 

Nato come associazione senza fini di 
lucro e con il chiaro intento di diffon- 
dere il PHP all'Italia e all'estero, il "Gruppo 
Utenti e Sviluppatori PHP" ha il suo bari- 
centro nel sito http://www.grusp.it. 
Non si tratta del solito sito, ma di una 
community organizzata sotto la forma di 
Wiki, dove ognuno può contribuire con 
articoli, documentazione, link trucchi è 
consigli. È interessante sia la forma asso- 
ciativa sotto cui il GRUSP nasce, ovvero 
un'associazione senza fini di lucro legal- 
mente riconosciuta, il che prelude alla 
volontà di dare continuità all'iniziativa, sia 
l'idea di basare la community su un Wiki 
piuttosto che sul classico blog o su un 
CMS chiuso. Il wiki consente di dare con- 
tinuità anche agli articoli proposti grazie 
al contributo libero che ciascuno può dare 
nella proposizione di questa o quella pre- 
cisazione. In bocca al lupo Grusp! 



http://www.ioprogrammo.it 



Aprile 2005/ 9 ► 



INBOX T Le risposte alle domande dei lettori 




Box 

l'esperto risponde... 



Quale linguaggio? 



Sviluppo applicazioni ma ora 
sono arrivato ad un punto 
molto importante: conosco e 
programmo in quasi tutti i lin- 
guaggi esistenti ma vorrei spe- 
cializzarmi su una piattaforma in 
particolare. Avevo pensato a .net 
affinando l'accoppiata C# e 
ASP.NET, poi ho pensato alla pos- 
sibilità di sviluppo multipiat- 
taforma windows-linux utilizzan- 
do java e jsp, infine c'è una terza 
strada rappresentata da PHP 
sempre potente e di facile com- 
prensione. Vorrei sapere da voi 
quale è la direzione del mercato 
e verso che linguaggio di pro- 
grammazione conviene orientar- 
si. Ringraziando anticipatamente. 
Giacomo 

Non è facile rispondere. Tutti i lin- 
guaggi hanno vantaggi e svantaggi 
e ciascuno viene utilizzato per le pro- 
prie pecurialità. Le ultime classifiche 
per quanto riguarda la diffusione dei 
linguaggi riportano la seguente statisti- 
ca: 



1 


C 


+1.63% 


2 


Java 


-4.22% 


3 


C++ 


-4.37% 


4 


PHP 


+3.02% 


5 


Perl 


-0.61% 


6 


Visual Basic 


-2.04% 


7 


SQL 


-0.14% 


8 


Python 


+1.50% 


9 


C# 


+0.19% 


10 

Fo 


Delphi/Kylix 
nte tiobe.com. 


+1.17% 



Nel tempo medio /lungo la massima 
crescita sembrerebbe essere attribuibi- 
le a Python, immediatamente seguito 
da PHP. Tuttavia non si può dire che 
questi due siano i linguaggi su cui pun- 
tare, molto dipende sulla tipologia di 
applicazione da realizzare. Per quanto 



riguarda il Web, PHP rappresenta senza 
dubbio un'ottima scelta. È anche vero 
che se devi sviluppare applicazioni 
molto legate agli ambienti Microsoft è 
opportuno puntare decisamente su 
Visual Basic.NET o C#. Per le applica- 
zioni Web che necessitino di particola- 
re sicurezza JSP è sicuramente un'otti- 
ma soluzione. 

Python è una scelta interessante per la 
creazione di script di sistema o di inter- 
facce di frontend verso applicativi for- 
mati da moduli separati. Come vedi 
non è possibile dare una risposta preci- 
sa. È importante capire esattamente 
quali sono le richieste che devi soddi- 
sfare, e poi scegliere il linguaggio ade- 
guato che rende meno problematico lo 
sviluppo dell'applicazione. 



C# o VB.NET: questo è il 
dilemma 

Cara ioProgrammo, mi sono da 
poco avvicinato al mondo 
della programmazione e vorrei 
cimentarmi con la piattaforma 
.NET. Sono un po' in dubbio sul 
linguaggio da scegliere: C# o 
Visual Basic? Voi cosa ne dite? 
Quali sono le differenze fra i due 
e cosa consigliereste a chi, come 
me, deve affrontare la scelta? Un 
grazie anticipato e mille compli- 
menti per l'ottimo lavoro! 

Mario 

Idue linguaggi che hai menzionato 
hanno molte somiglianze. Per capirne 
le differenze, partiamo dalla genesi: 
VB.NET è stato progettato per andare 
incontro alle esigenza degli sviluppatori 
Visual Basic, ampliando enormemente 
le possibilità offerte dalla vecchia piat- 
taforma VB 6. Visual C# è stato invece 
progettato con una sintassi e filosofia 
della piattaforma Java (Questa afferma- 
zione non la sentirete mai dalla bocca di 
un progettista Microsoft... ma siamo 



molto vicini alla realtà). Inoltre, tutto il 
framework .NET ricalca l'impostazione 
che Sun ha dato al suo gioiellino, in pri- 
mis con l'utilizzo della Virtual Machine. 
Quindi, per tornare al consiglio che chie- 
devi, direi che se cominci da zero puoi 
senz'altro adottare C# come linguaggio: 
forse richiederà uno sforzo iniziale leg- 
germente più grande, ma verrai ripagato 
ampiamente dalla migliore aderenza 
della sintassi alla filosofia .NET. Sce- 
gliendo Visual Basic .NET avrai pure 
sempre un ottimo linguaggio e potrai ot- 
tenere gli stessi risultati di C#, il pegno 
da pagare è però una certa forzatura nel 
piegare la sintassi Visual Basic alla se- 
mantica richiesta da .NET che è stretta- 
mente orientata agli oggetti. Insomma, 
se vuoi partire subito a razzo, prova con 
VB.NET, se invece puoi dedicare un po' 
di tempo e un po' di studio, ti consiglio 
vivamente di "attaccare" C#, uno dei mi- 
gliori linguaggi in circolazione. 



PHP & XML 

Buongiorno amici di 
ioProgrammo. Sto cercando di 
capire come parserizzare un file 
XML con PHP, e devo dire di avere 
più o meno ben chiaro tutto. 
Quello che non riesco a capire è 
come funziona XPath. Cioè mi 
pare di avere capito che posso 
fare delle interrogazioni su un file 
XML come se le facessi in SQL su 
un database, quello che non ho 
capito è come farlo in PHP e come 
funziona la sintassi di XPath. 

Romeo 

Buongiorno Romeo. Direi che il tuo 
intuito non ha sbagliato. XQuery è 
un linguaggio di interrogazione per 
documenti XML. Si tratta di una tecnica 
abbastanza potente che consente di 
recuperare un insieme di dati da un file 
XML senza doverlo parserizzare intera- 
mente e soprattutto recuperando stret- 



► 10 /Aprile 2005 



http://www.ioprogrammo.it 



Le risposte alle domande dei lettori ■ T INBOX 



tamente i nodi interessati dalla query. 
Viceversa utilizzando le normali interro- 
gazioni non sempre é possibile essere 
così precisi nel prelevare le informazioni 
che ci servono da un file XML senza 
dover ricorrere costosi costrutti condi- 
zionali. Un esempio sarà chiarificatore: 

<?php 

$xmldocument = new DOMDocument(); 
$xmldocument->load( 

'http://www.theregister.co.uk/excerpts.rss'); 
$xp = new DOMXPath($xmldocument); 
$nodelist = $xp->query( 

7/rss/channel/item/title"); 

foreach ($nodelist as $node) { 

print $node->textContent.'<br>'; 



?> 



Questo spezzone di codice recupera 
tutti i nodi title da un documento XML. 
Possiamo utilizzare una tecnica ancora 
più potente, utilizzando una query 
complessa. 

<?php 

$xmldocument = new DOMDocument(); 
$xmldocument->load( 

'http://www.theregister.co.uk/excerpts.rss'); 
$xp = new DOMXPath($xmldocument); 
$nodelist = 



$xp->query("//rss/channel/ 

item[substring(pubDate,9,3) 

='Jan']/title"); 

foreach ($nodelist as $node) 



{ 



print $node->textContent.'<br>', 



?> 



Recupera tutti i noti title tali che il campo 
pubDate di idem contenga la stringa 'Jan' 
La sintassi non è immediatamente intuiti- 
va. Un buon libro che spiega questi aspet- 
ti è quello pubblicato da Gianfranco For- 
lino per la collana "i libri di ioProgrammo" 
e dal titolo: "XML Guida alla Programma- 
zione". 



Controllare la registrazione 
di un dominio 

Salve cari Guru della programma- 
zione. Chiedo a voi lumi su una 
funzione che non riesco a realizza- 



re. Vorrei creare un'applicazione 
che consenta ad una persona di 
sapere se un dominio internet è 
libero oppure no. Ci sono parecchi 
siti su internet che svolgono questa 
funzione, ma non ho mai capito 
come fanno. Mi date una dritta? 

Giuseppe 

Ciao Giuseppe. Parliamo della situa- 
zione italiana. In Italia l'ente che si 
occupa di mantenere il registro dei 
domini attribuiti è il NIC http:/ 7 www 
.nic.it. Ovviamente non si occupa di 
mantenere semplicemente il registro, ma 
gestisce le deleghe e l'approvazione delle 
registrazioni, le cancellazioni e tutto 
quello che ha a che fare con i domini in- 
ternet. Delega ai singoli mantainer, quel- 
li a cui ci si rivolge di solito per la regi- 
strazione, il compito di fare da interme- 
diari fra l'utente finale e il nic. Il concet- 
to di delega è più ampio, ma direi che per 
la nostra spiegazione possiamo assume- 
re questo come valido. 
Il registro mantenuto dal Nic può essere 
interrogato mediante protocollo 
"whois". "Whois" è un servizio che gene- 
ralmente gira sulla porta 43 del sistema 
che lo mantiente. Esiste ovviamente il 
dominio "whois.nic.it" che mantiene un 
servizio di whois sulla porta 43 di un ser- 
ver che interroga il registro dei domini 
registrati. 

Interrogando un servizio whois si ottiene 
come risultato un testo che contiene lo 
stato del dominio. Per cui, riepilogando, 
per controllare se un dominio è registra- 
to oppure no, è opportuno controllare il 
registro dei domini tramite il protocollo 
whois. Perciò sarà necessario aprire un 
socket verso la porta 43 del server che 
mantiene il servizio whois, e poi parse- 
rizzare il file di testo risultante alla ricer- 
ca della stringa che testimonia se il 
dominio è stato registrato oppure no. In 
PHP ad esempio: 



} 

Goto... in Java!!! 



$domain = "www.pippopappo. 


it"; 


$fp = fsockopenC'whois.nic.it", 43, 

$errno, $errstr, 30); 


fputs($fp, "$domain\r\n"); 


while (!feof($fp)) { 


$buf = fgets($fp,128); 


if (ereg("No entries found " 


, $buf)) 


{ 


$result = "Non registrato" 


;} 



Gentile Redazione, sono un "vec- 
chio" programmatore Visual 
Basic che, tra sforzi e invettive, si 
sta convertendo a Java. Con mio 
sommo dispiacere, ho notato che in 
questo linguaggio (per altro vera- 
mente eccezionale) manca l'istru- 
zione GOTO... mi sbaglio? 
Vi prego, ditemi di sì! 

Riccardo 

Gentile Riccardo, devo dire che non ti 
sbagli! In Java, il commando GOTO 
non è presente e, fossi in te, non me ne 
rammaricherei più di tanto. Lo sforzo di 
costruire codice che non faccia uso di 
salti condizionati non potrà che giovare 
al tuo stile di programmazione. 
Comunque, se proprio non puoi farne a 
meno, puoi ricorrere ai break con eti- 
chetta che consentono di sporcare il 
codice a sufficienza! 
Di seguito trova un esempio 

class JavaGoto { 

public static void main(String args[]) { 
int max = 20; 



int limite = 10; 



int i 



out: { 



for( int riga=0; riga< max; riga++ ) 



±_ 



for( int col=0; col< max; col++ ) 
if( riga = = limite) break out; 



j += i; 



±_ 



System.out.println(i); 



// il ciclo si ferma con i pari a 5 



±_ 



} 



In questo caso il break riesce a rompere 
ben due cicli innestati... non so se fa al 
caso tuo, ma è quanto di più vicino al 
Goto esista in Java! 



PER CONTATTARCI 

e-mail: ioprogrammo@edmaster. it 

Posta: Edizioni Master, 

Via Ariberto, 24 - 20123 Milano 



http://www.ioprogrammo.it 



Aprile 2005/U ► 



NEWSGROUP TU meglio dei Newsgroup 




NEWS GI up 

Le informazioni nella 



Le informazioni nella Rete 



uirexxamenxe aai Torum ai lorrogrammo le discussioni più "Hot" del momento 



Come ottenere il percorso 
.NET Framework 

Avrei bisogno di un metodo 
veloce per conoscere in modo 
programmatico la posizione del 
.NET framework nel computer che 
esegue un'applicazione, come 
posso fare? 

Risponde Salvatore Meschini 

http://forum.ioprogtammo.net/thread.php? 

threadid=4726&boardid=36 

Il sorgente va salvato in un file (es. getpath 
xs). Si digiti: esc Itargetiwinexe getpath.cs 
In alternativa scaricate il programmino 
Snippet Compiler da httpj/www.sliver 
.corri. Il pezzo di codice che risolve il pro- 
blema è il seguente: 

using System; 

using System.IO; 

using System. Windows. Forms; 
public class WindowsForm : 

System. Windows. Forms. Form 

{ 

public static void MainQ { 



Application. Run(new WindowsForm()); 



±_ 



private string CLRPathQ { 



Object CLR = new ObjectQ; 



return Path.GetDirectoryName( 

CLR.GetTypeQ.Assembly. Location);} 



public WindowsForm() { 



MessageBox.Show(CLRPathQ); 

} 

} 

Elencare le unità di rete 
con WMI 

Talvolta può essere necessario 
disporre dell'elenco delle unità 
di rete configurate sul proprio PC, 
determinarne lo stato della 
connessione, se questa verrà 
ripristinata al riavvio del sistema o 
conoscere il percorso remoto del 



disco mappato come unità. 
Per ottenere in maniera semplice 
queste ed altre informazioni con 
Visual Basic, si può ricorrere a WMI 

SimoneVB 

http:/ /torum. io programmo, net/thread.php ?threa- 

did=4703&boardid=36 

Il codice proposto da SimoneVB è il se- 
guente: 

Private Sub Form_Load() 

If Not IsWMHnstalledQ Then 

MsgBox "L'applicazione richiede Microsoft 
Windows Management Instrumentation 
(WMI).", vbCritical 

Exit Sub 

End If 

Dim oLoc 

Dim oServ 

Dim oObjectSet 

Dim oConn 

Dim sMsg As String 

Const sWQL As String = "SELECT * FROM 
Win32_NetworkConnection" ' query WQL 

Set oLoc = CreateObject("WbemScripting 
.sWbemLocator") ' oggetto locator 

Set oServ = ol_oc.ConnectServer( 
".", "root\cimv2") 

Set oObjectSet = oServ.ExecQuery(sWQL) 

For Each oConn In oObjectSet 



Set oConn = Nothing 



Print 



sMsg = "Unità di rete: " & oConn.LocalName 
sMsg = sMsg & vbCrLf & "Path remoto: " 

& oConn.RemotePath 
sMsg = sMsg & vbCrLf & "Ripristino 

connessione all'avvio di Windows: " 

& oConn.Persistent 

sMsg = sMsg & vbCrLf & "Tipo di risorsa: " 

& oConn.ResourceType 

sMsg = sMsg & vbCrLf & "Stato: " 

& oConn.Status 

sMsg = sMsg & vbCrLf & "Stato 

connessione: " & oConn.ConnectionState 
sMsg = sMsg & vbCrLf & "Commento: " 

& oConn.Comment 
MsgBox sMsg, vblnformation, "Unità di rete" 
Next 



Set oObjectSet = Nothing 



Set oServ = Nothing 



Set oLoc = Nothing 



End Sub 



Function IsWMHnstalledQ As Boolean 



Dim oTemp 



On Locai Error Resumé Next 
Set oTemp = CreateObject( 

"WbemScripting. sWbemLocator") 
IsWMHnstalIed = (Err.Number <> 429) 

If Err.Number = 429 Then 

Err.Clear 
Else 



Set oTemp = Nothing 



End If 



End Function 

Tomcat con Windows XP 

Salve, qualcuno ha provato a far 
funzionare php con Tomcat su 
Windows XP? 

Poi mi sono arreso l'ho configurato 
con Apache e in 3 secondi ha fun- 
zionato. 

Avrei però bisogno di integrare PHP 
e TOMCAT. Qualcuno mi può 
aiutare? Grazie. 

Santix 

http:/ /torum. ioprogrammo. net/thread.php ?threa- 

did=4809&boardid=2 

Risponde doc 

Non so quale procedura tu abbia usato, io 
tempo fa ne ho usata una riportata sul 
Wiki di Jakarta e ha funzionato: 

• Devi definire le solite variabili d'am- 
biente 

$JAVA_HOME / $TOMCAT_HOME, $PHP_HOME 

• Per quanto riguarda PHP al configure 
devi passare i seguenti parametri 

./configure — with-servlet=$TOMCAT_ 

HOME -with-java=$JAVA_HOME 



► 12/Aprile 2005 



http://www.ioprogrammo.it 



Il meglio dei Newsgroup 



T NEWSGROUP 



• Quindi dopo il make hai due file che ti 
servono, sapi/servlet/phpsrvltjar e libs 
/Ubphp4.so 

• copi il file jar dentro $TOMCAT_ 
HOME/common/lib 

• copi $PHP_HOME/sapi/servlet/web 
.xml (servlet e servlet-mapping) den- 
tro il file $TOMCAT_HOME /conf/web 
.xml 

• ridefinisci la variabile LD_LIBRARY_ 
PATH=$PHP_HOME/libs a livello di 
sistema . 

Poi c'è anche uno script per cambiare la 
configurazione di PHR visto che dalla ver- 
sione 4.x alla 5.x Tomcat ha cambiato la 
locazione e il nome del jar riguardante le 
servlet 



- configure.org 2004-04-07 

11:20:24.000000000 



-0200 



+ + + configure 2004-04-07 

11:22:50.000000000 +0200 

if test "$withval" = "yes"; then 



SERVLET_CLASSPATH= 



else 



+ if test -f $withval/common/lib 

/servlet-api.jar; then 

+ SERVLET_CLASSPATH = $withval 

/common/lib/servlet-api.jar 

+ fi 

-I- 

if test -f $withval/lib/servlet.jar; then 

SERVLET_CLASSPATH=$withval/lib/servlet.jar 

fi 



Collegare due computer 
in Rete 

Ciao a tutti. ..vi voglio porre un 
problema... possiedo due com- 
puter, uno equipaggiato con w2k e 
sp4 e l'altro con XP, e un hub... 
voglio collegarli e creare una picco- 
la rete ma dopo innumerevoli ten- 
tativi ancora non ci riesco... . 
Qualcuno potrebbe illuminarmi 
magari spiegandomi i passi neces- 
sari? 
Grazie e ciao a tutti 



http://forum.ioprogrammo.net/threacl.php7threaclitl 
=4875&boardid=31 



chine come segue 

TCP-IP sulla prima macchina 

IP: 192.168.1.2 

GateWay: 192.168.1.1 

NetMask: 255.255.255.0 

DNS: quello che ti dice il tuo provider 

TCP-IP sulla seconda macchina 
IP: 192.168.1.3 
GateWay: 192.168.1.1 
NetMask: 255.255.255.0 
DNS: Stesso DNS di prima 

Poi fai un ping dalla prima alla seconda da 
una console di MSDOS 

ping 192.168.1.3 

se risponde sei a posto, altrimenti qualco- 
sa non va. Controlla che i cavetti siano 
buoni, oppure controlla la scheda di rete. 
Ovviamente se devi andare in internet una 
delle due deve fare da router, oppure devi 
prendere un router esterno. 
Se una delle due deve fare da router, il 
wizard per la condivisione della connes- 
sione farà le impostazioni per te. 

Trovare le cinque 
directory più recenti 

Salve a tutti. Vorrei sviluppare un 
piccolo software per fare una 
ricerca nel sistema e trovare le 5 
directory più" recenti. Il problema e" 
che non so proprio da dove iniziare, 
lo con l'università ho fatto al massi- 
mo lettura da file. Non e 1 che mi 
potete consigliare uno schema logi- 
co da seguire. 

Al max provare a svilupparlo insie- 
me. Grazie 

MaTz! 

http://forum.ioprogrammo.it/thread.php7thre 

adid=4913&boardid=20&styieid=1 



long hFile; 



Devi configurare il TCP /IP sulle due mac- 



Ecco l'esempio... 



#include "stdafx.h" // Per Visual C+ + 
#include <stdio.h> 
#include <io.h> 
#include <time.h> 
void main( void ) { 

struct _finddata_t c_file; 



/* Cerca il primo file nella directory corrente */ 
if( (hFile = _findfirst( "*.*", &c_file )) == -IL) 
printf( "Non ci sono file nella 
cartella corrente!\n" ); 



else { 



printf( "Lista di tutti i file\n\n" ); 

printf( "\nRDO HID SYS ARC DIR FILE 
DATE %25c SIZE\n", ' ' ); 



printf( "- 



— %25c — -\n", ' ' ); 



printf( ( c_file.attrib &_A_RDONLY ) ? 
" Y " : " N " ); 

printf( ( c_file.attrib &_A_HIDDEN ) ? 
" Y " : " N " ); 

printf( ( cjile.attrib & _A_SYSTEM ) ? 
" Y " : " N " ); 

printf( ( cjile.attrib & _A_ARCH ) ? " 
Y " : " N " ); 

printf( ( cjile.attrib &_A_SUBDIR ) ? " 
Y " : " N " ); 

printf( " %-12s %.24s %9ld\n", 

c_file.name, ctime( &( c_file.time_write 

) ), c_file.size ); 

/* Cerca tutti gli altri file */ 

while( _findnext( hFile, &c_file ) 
== 0){ 



printf( ( c_ 


Jile.attrib & _A_ 


_RDONLY 




)? 


' Y " 


: " N " ); 


printf( ( c_ 


Jile.attrib 


&_A_ 


JHIDDEN 




)? 


' Y " 


: " N " ); 


printf( ( c_ 


Jile.attrib 


&_A_ 


.SYSTEM 




)? 


' Y " 


: " N " ); 


printf( ( c_ 


Jile.attrib 


&_A_ 


_ARCH ) 




? 


' Y " 


: " N " ); 


printf( ( c_ 


Jile.attrib 


&_A_ 


_SUBDIR 




)? 


' Y " 


: " N " ); 



printf( " %-12s %.24s %9ld\n", 

c_file.name / ctime( &( 
c_file.time_write ) ), c_file.size ); 



±_ 



Jindclose( hFile ); 



} 



Naturalmente, tutto dipende da dove inizi 

la ricerca (cartella di partenza). 

Per il resto puoi studiarti un po' la struct 

_finddata_t 



SERVIZIO CLIENTI 

e-mail: sevizioclienti@edmaster.it 
Tel. 02 83 12 12 

SOSTITUZIONE CD 

Inviare il CD Rom difettoso in busta chiusa 
a: Edizioni Master Servizio Clienti 
Via Ariberto, 24 - 20123 (MI) 



http://www.ioprogrammo.it 



Aprile 2005/13 ► 



COVER STORY ▼ 



Sphinx4 



Riconosce le parole e le restituisce all'applicazione 

Hi parli 

Java risponde 

Impariamo a utilizzare Sphinx4, una tecnologia che ultimamente 
ha avuto una forte diffusione soprattutto per la sua capacità 
di riconoscere e analizzare la voce 




U CD U WEB 



^ 




I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 




\ J2SE SDK, Sphinx4 



Tempo di realizzazione 



Per riconoscimento vocale si intende la possi- 
bilità da parte di un computer capire le parole 
pronunciate dall'utente. Grazie ad una gram- 
matica che definisce le parole riconoscibili, un pro- 
gramma per il riconoscimento vocale analizza il 
flusso audio ricevuto e restituisce le parole che crede 
di aver capito. Questa è una tecnologia che ultima- 
mente ha avuto una forte diffusione, soprattutto per 
quanto riguarda cali center e servizi di informazioni 
automatizzati. Esistono chiaramente diverse imple- 
mentazioni, anche hardware, per il riconoscimento 
vocale e noi andremo a vedere come sia semplice 
utilizzare un'implementazione software per Java, 
Sphinx4. 



SPHII\IX4 B 

UHI RICONOSCITORE 

VOCALE IH! JAVA 

Sphinx4 è un riconoscitore vocale scritto totalmente 
in Java, basato su HMM [Hidden MarkovModels), un 
modello statistico usato per il riconoscimento, e 
deriva dal predecessore Sphinx3. Nato da un proget- 
to universitario, Sphinx4 si contraddistingue per es- 
sere il primo riconoscitore vocale OpenSource (cosa 
non da trascurare in questo campo dell'informati- 
ca). Si può definire un vero e proprio framework per 
lo sviluppo di applicazioni vocali, vista la grande 
quantità di API e tool disponibili. Sphinx4 permette 
il riconoscimento di due diverse modalità: live e 
batch. Live quando il programma analizza dei flussi 
audio generati in quell'istante, mentre la modalità 
batch permette l'analisi di un file wav contenente un 
flusso audio registrato precedentemente. Attraverso 
una configurazione che deve essere fornita a 
Sphinx4, quest'ultimo riesce a riconoscere determi- 
nate parole e a restituirle all'applicazione. Questo ri- 
conoscitore permette inoltre di avere un punteggio 
di riconoscimento della parola, ovvero una stima di 



sicurezza per la parola appena riconosciuta. Inoltre 
vengono date diverse possibilità per definire la 
grammatica, che definisce il linguaggio da ricono- 
scere, come JSGF (Java Speech Grommar Format), 
formato di specifica delle grammatiche della SUN. 
Chiaramente l'approccio ad un tool con tantissime 
feature come Sphinx4 può risultare un po' ostico, 
soprattutto per quanto riguarda terminologie e 
aspetti noti soltanto a persone che hanno già avuto 
a che fare con riconoscitori vocali e tecnologie ana- 
loghe. Infatti all'interno di questo framework è pre- 
sente un file di configurazione abbastanza comples- 
so, che deve essere editato per decidere quali com- 
ponenti si vogliono utilizzare e quali no, quali pro- 
prietà settare etc etc. Nonostante ciò noi vedremo 
insieme la realizzazione di un semplice programma 
Java che utilizza le potenzialità di Sphinx4 in manie- 
ra molto semplice, senza dover essere degli esperti 
del riconoscimento vocale. 



CONFIGURAZIONE 

Prima di poter utilizzare Sphinx4 è necessario capi- 
re la configurazione che necessita questo tool. Ogni 
programma che utilizza il riconoscimento vocale at- 
traverso questo framework deve necessariamente 
avere un file di configurazione, un file dove sono 
presenti tutti i componenti che si devono utilizzare, 
dove vengono settate diverse proprietà importanti. 
Una grande limitazione è data dal fatto che non pos- 
siamo riconoscere direttamente parole italiane, 
visto che il dizionario di default è stato fatto per 
parole inglesi. La definizione di un nuovo dizionario 
non è nulla di trascendentale, ma sicuramente è 
poco pratica da spiegare in un articolo. Quindi ci 
adatteremo ad utilizzare un dizionario inglese pre- 
sente nella distribuzione ufficiale di Sphinx4. Il 
dizionario da utilizzare viene richiamato da Sphinx4 
nel file di configurazione nel seguente modo: 



V 16 /Aprile 2005 



http://www.ioprogrammo.it 



Sphinx4 ■ T COVER STORY 



<component name="dictionary" type= 

"edu.cmu.sphinx.linguist.dictionary.FastDictionary"> 
<property name="dictionaryPath" value="resource: 

/edu. emù. sphinx. model. acoustic.WSJ_8gau_13dCep_l 
6k_40mel_130Hz_6800Hz. Model !/edu/cmu/sphinx/ 

model/acoustic/WSJ_8gau_13dCep_16k_40mel_130Hz 

_6800Hz/dict/cmudict.0.6d"/> 

<property name="fillerPath" value="resource: 

/edu. emù. sphinx. model. acoustic.WSJ_8gau_13dCep_l 
6k_40mel_130Hz_6800Hz. Model !/edu/cmu/sphinx/ 

model/acoustic/WSJ_8gau_13dCep_16k_40mel_130Hz 

_68Q0Hz/dict/fillerdict"/> 

<property name="addSilEndingPronunciation" 

value="false"/> 

<property name="allowMissingWords" value="false"/> 
<property name="unitManager" value="unitManager"/> 
</component> 

Come potete vedere le dichiarazioni che vengono 
fatte sono molto intuitive. Viene definito il compo- 
nente dizionario [dictionary] e vengono settate di- 
verse proprietà del dizionario, prima fra tutte la lo- 
cazione. Quindi se dovessimo cambiare dizionario 
(già all'interno di Sphinx4 ne sono presenti diversi 
per diversi scopi) dovremmo ritoccare questa defi- 
nizione nel file di configurazione del nostro pro- 
gramma. Altra parte che non possiamo tralasciare 
riguarda la definizione della grammatica che verrà 
utilizzata nel nostro programma. Questa viene defi- 
nita sempre come un componente e quindi inserita 
nella configurazione che dobbiamo fare 

<component name="jsgfGrammar" type= 

"edu.cmu.sphinx.jsapi.JSGFGrammar"> 
<property name="dictionary" value="dictionary"/> 
<property name="grammarl_ocation" value="."/> 
<property name="grammarl\lame" value="slideshow"/> 
<property name="logMath" value="logMath"/> 

</component> 

Il nome della grammatica, che definiamo di tipo 
JSGF (è possibile definire anche grammatiche in al- 
tri formati), è "slideshow" quindi nella directory del 
nostro programma oltre al file di configurazione do- 
vremo avere il file "slideshow.gram". Questi due set- 



4.5 


Sphinx-4 

h < zm ■« u*S'"a mn*l m *ìs> « >' J \,<i »j nummi (» v^i ^ 


Sphinx-4 Links 

• Proiect Pane 

• 

SMJ SDhmB 


General Information 

Installatìon 




Sphint-ITWiki 




Building 


T 


Sphinx-4 in Detaii 






. 






l«™«*K«arl 



taggi sono obbligatori per sviluppare un'applicazio- 
ne, visto che comunque dovremo definire una no- 
stra grammatica e richiamarla in un nostro file di 
configurazione. Gli altri componenti che non ven- 
gono qui riportati richiedono un più attento studio 
di caratteristiche del riconoscimento, che in questo 
sede non sono di nostro interesse. 



ESEMPIO 

DI APPLICAZIONE 

Vediamo ora come poter sviluppare una nostra ap- 
plicazione, abbastanza semplice, per usufruire di 
questo framework. Il programma che vogliamo svi- 
luppare è un semplice SlideShow di immagini, che 
può essere azionato attraverso dei comandi vocali. 
Una cosa del genere potrebbe essere utile per le pre- 
sentazioni o per le lezioni dove il relatore può tran- 
quillamente essere lontano dal computer che 
proietta le immagini da 
presentare. Il funziona- 
mento è abbastanza ba- 
nale: dobbiamo permet- 
tere al nostro programma 
di riconoscere i comandi 
"Nexf ' e "Back" per poter 
rispettivamente andare 
avanti e indietro nella no- 
stra presentazione di im- 
magini. Inoltre possiamo 
prevedere di far visualiz- 
zare ulteriori informazio- 
ni riguardanti la slide richiamando il comando 
"About". Quindi prima di tutto dobbiamo definire 
una nostra grammatica, in base alla quale il nostro 
programma potrà capire quale comando gli è stato 
dato. 



DEFINIZIONE 

DELLA GRAMMATICA 

Per la definizione della grammatica utilizzeremo 
JSGF. Questo è uno standard della SUN che viene 
utilizzato per descrivere le grammatiche in pro- 
gramma di riconoscimento vocale. Praticamente al- 
l'interno di un semplice file vengono definiti dei co- 
mandi che poi verranno interpretati dal riconoscito- 
re. Nel nostro caso dobbiamo definire pochi coman- 
di, ecco quindi di seguito la grammatica che utiliz- 
zeremo. 





Fig. 2: Un programma d'esempio con Java Web 
Start, disponibile sul sito ufficiale 



Fig. 1: L'homepage di Sphinx4 



#JSGF V1.0; 


/** 


* slideshow.gram: 


Grammatica da utilizzare 
programma SlideShow 


nel 
vocale 


*/ 


grammar slideshow; 



Il riconoscimento e la 
sintesi vocale sono dei 
campi di ricerca molto 
attivo in questi tempi. 
Sono molte le 
specifiche e i prodotti 
che sono presenti ora, 
molti anche i tool per 
sviluppatori. 
http://www.research.att. 
com/projects/tts/demo.html 



http://www.voiceobjects. 
com/eng/produets/index. 
shtml 

http://www.loquendocafe. 
com/ 



http://www.ioprogrammo.it 



Aprile 2005/ 17 ► 



COVER STORY T 



Sphinx4 




public <comando> = ( next | back | about ); 

public <uscita> = (exit | quit); 

In questo modo abbiamo definito due diversi co- 
mandi. Il primo lo utilizzeremo per manovrare lo Sli- 
deShow, mentre il secondo per uscire dall'applica- 
zione. Abbiamo definito i comandi in inglese perché, 
come detto precedentemente, per utilizzare delle 
parole in italiano dovremmo scrivere un dizionario 
italiano per Sphinx4, che va oltre le finalità di questo 
articolo. Ora che la definizione della semplice gram- 
matica è stata fatta, bisogna implementate la parte 
riguardante il vero e proprio riconoscimento. 



RICONOSCIMENTO 
DEI COMANDI 

A questo punto dobbiamo utilizzare Sphinx4 per po- 
ter riconoscere il flusso audio esterno. Allora, prima 



di tutto, dobbiamo importare i package necessari 
per il nostro compito 

import edu.cmu.sphinx.frontend.util.Microphone; 



import edu.cmu.sphinx.recognizer.Recognizer; 



import edu.cmu.sphinx.result.Result; 



import edu.cmu.sphinx.util.props.ConfigurationManager; 



import edu.cmu.sphinx.util.props.PropertyException; 

La prima cosa da fare ora è passare il file di configu- 
razione a Sphinx4. Già abbiamo parlato di questo fi- 
le di configurazione in XML, lungo e tedioso da 
compilare. Per evitare di perdersi in una lunga di- 
scussione immagineremo di avere a disposizione un 
nostro file di configurazione (in realtà lo trovate in- 
sieme al codice sul CD della rivista). Richiamiamo 
quindi il file di configurazione all'interno del nostro 
programma 

URL uri = SlideShow. class. getResource( 



SEI PASSI PER COMINCIARE 



DOWNLOAD DI SPHINX4 E ESTRAZIONE FILE CLASSPATH 



INIZIALIZZAZIONE COMPONENTI 



111. mc .»I><| fin»-! ■-, 11M -» 1 Uh 1 


Rie Modifica Visualizza Preferiti Strumenti ? 


Q indietro - Q ■ $ | p Cerca ^Cartelle ^ 


indirizzo 


3 crea nuova cartella 
£ Fijbbl..:5-:5rfr-ll- 3 --ijl v-v-b 
B Condividi cartella 


[ ^ index.html [~h license.terms 
fj HTMLDocument UffH] Fife 

\m\ s dme h sr 5E ~ NOTE5 


Q=P4 
Q Documenti 
Q Documenti condivisi 
9 Risorse del computer 
«Risorse di rete 


Dettagli C*) 
sphin H 4-l.ubeta 



DDopo aver scaricato la distribuzione 
di Sphinx4 dal sito http://cmusphinx 
■sourceforge.net/sphinx, scegliamo una 
cartella dove estrarre lo zip che crea una 
cartella con tutte le librerie, documenta- 
zione ed eseguibili organizzati. 

SETUP DI JSAPI 



*»\-^ 



Cartelle "jTTTJ^ 

.;.tot.i5phiru-nsp'!\sph;rìrf- i . Cibet.riijib 



Operazioni file e cartella 

^j Rinomina file 

^ Sposta file 

IQ Copia file 

Q Pubblica file sul Web 

Q Invia il file per porta 



\ = 



'^W*» 



§3 jsapi jar file Setup: Compieteci 



Altre risorse 

Q sphinxt-l.Obeta 
Q Documenti 
Q Documenti condivi. 
g Risorse del compul 
«4 Risorse di rete 



Dettagli 

Applicartene 



J 83 KB 

V — DI 



_| Nuli 






B All'interno della sottocartella lib 
troviamo l'eseguibile jsapi.exe (o 
jsapi.sh per Linux) che ci permette di 
installare JSAPI sul nostro sistema 
semplicemente avviandolo. 



-JDKTooIs 

.-- - 
Code nsertioi 

HI; -:-r -Jzil] 



Name: |j2sdk1 4.2_01 

Home path : |C:\j2sdk1.4.2_0n 

Classes I Soli 



J 



| Documentation | 



i i_ Jl M __nl li iit < i 

C:\i2sdk1.4.2_01\lib\dt.jar 

C:\i2sdk1.4.2_01\libMools.iar 

1 i_ J I ' _Ji| i- In - I Jil 1 | 
' i ' J' I ,4.2_01 ' in l,i -f ». . [ 
C il di I -* jjjl'ìie it :.i'ic * I=. 
C il -di I A j_0r.ir.;-!t :-•!',. i i„:«_r; 






L 



T 



T 



PPer utilizzare Sphinx4 in un nostro 
programma dobbiamo avere inseri- 
to nel dasspath \jar necessari. Questo 
possiamo farlo o definendolo a livello del 
nostro sistema, modificando la variabile 
CLASSPATH o definendolo all'interno del 
nostro ambiente di lavoro (ad esempio in 
JCreator). I jar da aggiungere sono 
presenti nella sottocartella lib. 



SETUP DEL PROGETTO 

iiui-diiei.udii 



:onfig.xnnl.bak 



^rann.bak 



J3 



jnutoi iuw^yyii iu.uw.udii 
File CLA55 
1 KB 



n 



5lide5how.java 
ource File 



PPer utilizzare Sphinx4 in un nostro 
programma dobbiamo necessaria- 
mente definire un file XML di configura- 
zione (trovate l'esempio incluso nel CD e 
nella distribuzione di Sphinx4) e un file 
per definire la grammatica delle parole 
da riconoscere. 



URL uri = SlideShow.class.getResource( 

"slideshow.config.xml") 



ConfigurationManager cm = 

new ConfigurationManager(url) 
Recognizer recognizer = (Recognizer) 
cm.lookupC'recognizer") 



Microphone microphone = (Microphone) 

cm.lookup("microphone") 



recognizer.allocateQ; 



Ora possiamo direttamente passare 
Km alla scrittura del codice, richiaman- 
do all'interno del nostro programma i 
componenti principali per il riconosci- 
mento: Recognizer e Microphone. 

EFFETTUARE IL RICONOSCIMENTO 



if (microphone. startRecording()) 

{ 
Result result = recognizer.recognizeQ; 



if (result != nuli) 



{ 



String resultText = 

result.getBestFinalResuItNoFillerQ; 
System. out.println("Comando 

pronunciato: " + resultText + "\n"); 



Concludiamo con il vero e proprio 
riconoscimento. In base alla 

grammatica da noi definita e al flusso 

audio che viene riconosciuto, la classe 

Result ci restituisce la stringa 

riconosciuta. 



► 18 /Aprile 2005 



http://www.ioprogrammo.it 



Sphinx4 ■ T COVER STORY 



"slideshow.config.xml"); 



ConfigurationManager cm = new ConfigurationManager(url); 

Ora il Manager delle configurazioni di Sphinx4 co- 
nosce cosa vogliamo utilizzare. Infatti solo ora pos- 
siamo istanziare i diversi tool che dovremo utilizza- 
re durante il nostro programma. In questo semplice 
caso dobbiamo avere a disposizione soltanto un og- 
getto Microphone, che rappresenterà appunto il mi- 
crofono del nostro computer, e un oggetto Recogni- 
zer, che riconoscerà il flusso audio in base anche alla 
grammatica che abbiamo definito precedentemen- 
te. Per istanziare questi due oggetti dobbiamo ap- 
punto passare attraverso il ConfigurationManager 
come illustrato qui di seguito 

Recognizer recognizer = (Recognizer) 

cm.lookup("recognizer"); 

Microphone microphone = (Microphone) 

cm.lookupC'microphone"); 

Istanziato il riconoscitore e il microfono dobbiamo 
procedere nel seguente modo: prima dobbiamo es- 
sere certi che il microfono stia registrando, poi dob- 
biamo dire al riconoscitore di processare il flusso au- 
dio. In questo modo lasciamo in attesa il riconosci- 
tore fino a quando non trova una parola conosciuta, 
in tal caso effettuiamo l'operazione richiesta 

recognizer.allocateQ; 

if (microphone.startRecordingQ) { 

System. out.println("Microfono in registrazione."); 

while (true) { 



Result result = recognizer.recognizeQ; 



if (result != nuli) { 



//Adesso controlliamo il risultato ottenuto dal 

//riconoscitore attraverso la classe Result e ci viene 
//restituito il risultato che ha la maggiore affidabilità 
//in base alla grammatica che abbiamo definito 



String resultText = 

result. getBestFinalResultNoFiller(); 
System. out.println("Comando pronunciato: " + 

resultText + "\n"); 

//In questo punto dovremo effettuare uno switch 
//sui vari comandi presenti nel nostro programma 



//e in base al comando riconosciuto avviare una 



//determinata funzione 



} else { 



System.out.println("Comando non pronunciato"); 



}}}} 



else { 



System. out.println("Impossibile avviare la 
registrazione."); 



recognizer.deallocateQ; 



System. exit(l); } 

Attraverso queste semplici righe di codice abbiamo 
quindi il controllo di cosa viene detto dall'utente e 



quindi rimane soltanto da implementare il vero e 
proprio programma di SlideShow. 



GUI 

Per quanto riguarda le parte grafica della nostra ap- 
plicazione utilizzeremo un Layout grafico che fa al 
caso nostro: CardLayout Questo layout, che fa parte 
di AWT (Abstract Widget Toolkit), permette di inseri- 
re un certo numero di pannelli che vengono richia- 
mati e mostrati a schermo in una certa sequenza. 
Praticamente quando noi 
salviamo dei pannelli in 
questo layout diamo anche 
una stringa che identifica 
questo pannello. Successi- 
vamente quando vorremo 
visualizzare un determina- 
to pannello CardLayout si 
comporterà come una ta- 
bella di Hash: passando 
semplicemente la stringa 
che identifica il pannello lo 
potremo richiamare e vi- 
sualizzarlo a schermo. 
Quindi nel programma che 
stiamo costruendo utilizzeremo questo componen- 
te, decidendo (dinamicamente o staticamente) 
quali sono i file da dover visualizzare ed inserendoli 
in questo layout. Poi successivamente dovremo scri- 
vere la parte di controllo del nostro programma che, 
in base alle parole riconosciute da Sphinx4, mano- 
vrerà adeguatamente i vari pannelli. Allora prima di 
tutto definiamo come saranno strutturati i vari pan- 
nelli che faremo visualizzare al nostro programma. 
Dobbiamo suddividerli in pannelli contenenti una 
slide e pannelli contenenti approfondimenti (quindi 
testuali). Nel pannello contenente una slide dovre- 
mo semplicemente stampare a schermo l'immagine 
che viene passata nel costruttore 





Le parole che 

vengono 

riconosciute, in 

base alla 

grammatica 

definita, vengono 

notificate alla parte 

di controllo 



V 



In base alle parole 

che sono state 

riconosciute 

vengono impartiti 

determinati 

comandi 

all'interfaccia 

grafica 



Fig. 3: Lo schema dell'applicazione 



class ImmPanel extends JPanel { 



Image image; 



public ImmPanel(Image image) { 



this. image = image; 



this.setBorder(BorderFactory.createTitledBorder( 
BorderFactory.createEtchedBorder( Color.black, 

Color.blue ),"SlideShow by IoProgrammo") );} 

public void paintComponent(Graphics g) { 



super.paintComponent(g); 



g.drawImage(image,0,0,this.getWidth(), 

this.getHeight(),this);} } 

Per quanto riguarda il pannello di approfondimento 
richiameremo dinamicamente dei file testuali e mo- 
streremo un'informazione sulla diapositiva tramite 
JOptionPane, ovvero visualizzando un semplice 



K2?M 

L'IBM è una società 
molto attiva nel campo 
del vocale. 
Ultimamente ha 
dichiarato che rilascerà 
il suo riconoscitore 
vocale come progetto 
opensource. Sul sito di 
AlphaWorks sono 
disponibili molti tool 
per lo sviluppo di 
applicazioni vocali. 
http://www.al phaworks. 
ibm.com/tech/voiceportal 



http://www.al phaworks. 

ibm.com/tech/ 

embeddedvoicetk 



http://www.ioprogrammo.it 



Aprile 2005/ 19 ^ 



COVER STORY T 



Sphinx4 




PopUp. Quindi la classe che implementeremo servi- 
rà per caricare il file delle informazioni aggiuntive 
della diapositive e successivamente per richiamarle 
all'interno del programma 

class Info{ 

String file, linea; 
Vector info=new VectorQ; 



System .exit(O); 



public InfoPanel(String file) { 



this.file=file; 



try{ 



JSGF (Java Speech 
Grammar Format) è un 
formato che permette 
di definire la grammati- 
ca da utilizzare in appli- 
cazioni vocali. È stato 
definito all'interno di 
JSAPI (Java Speech API), 
specifica della SUN per 
lo sviluppo di applica- 
zioni vocali. 
http://java.sun.com/produc 
ts/java- 
media/speech/forDevelope 
rs/JSGF/ 
http://java.sun.com/produc 
ts/java-media/speech/ 



BufferedReader br=new BufferedReader(new 
InputStreamReader(new FileInputStream(new 

File(file)))); 

while ((linea = br.readl_ine())! = nuli) 



info.add(linea);} 



catch (Exception e) { 



info.add("Nessuna informazione trovata");}} 



public String getAbout(int i) { 



1 




Fig. 5: II risultato che otteniamo. 



Oltre a Sphinx4, esisto- 
no altre implementazio- 
ni di riconoscitori voca- 
li. Ecco un paio di link 
di altri famosi prodotti 
da poter utilizzare 
http://www.cloudgarden. 
com/ 
http://www.lhs.com/ 
http://www.microsoft.com/ 
speech/ 



return (String)info.elementAt(i-l);}} 

Ora che abbiamo completato la definizione dei vari 
pannelli da vedere dobbiamo pensare alla parte di 
programma che farà da ponte tra il comando che 
viene riconosciuto e quello che dobbiamo visualiz- 
zare. 



CONTROLLER 

Rimane soltanto da inserire il motore alla nostra 
applicazione. Per fare ciò sono sufficienti poche ri- 
ghe di codice. Abbiamo 
già il risultato del ricono- 
sci mento vocale, ottenuto 
tramite la classe Result di 
Sphinx4. Questa classe ci 
restituisce, analizzando il 
flusso audio, la parola che 
viene pronunciata. A que- 
sto punto, avendo definito 
poche e semplici comandi 
dovremo soltanto imple- 
mentare uno switch e di 
volta in volta eseguire l'o- 
perazione appropriata. Ecco quindi lo switch da 
inserire nel nostro programma 



■ 



if (resultText.equals("next")) { 



cardManager.next(ImPanel); 



visualizzanda+ + ;} 



else if (resultText.equals("back")) { 



cardManager.previous(ImPanel); 



visualizzanda--; } 



else if (resultText.equals("about")) { 



String news=info.getAbout(visualizzanda); 
JOptionPane.showMessageDialog(sl,news); } 



else if (resultText.equals("quit")) 



System. exit(O); 

Così, tutta l'applicazione è ai comandi della nostra 
voce, facendo andare avanti e indietro le slide, mo- 
strando info aggiuntive e uscendo dal programma. 



else if (resultText.equals("exit")) 



DELL'APPLICAZIONE 

Per avviare la nostra applicazione dobbiamo essere 
sicuri di avere bene configurato il microfono sul no- 
stro computer, altrimenti il nostro programma non 
potrà riconoscere niente. Una volta configurato 
dobbiamo includere nel nostro classpath le librerie 
di Sphinx4, che troviamo nella cartella lib della di- 
stribuzione scaricabile dal sito di Sphinx4 (http:// 
cmusphinx.sourceforge.net/sphinx4/). All'interno del- 
la cartella lib troviamo anche l'eseguibile per in- 
stallare JSAPI sul nostro sistema, jsapi.exe per Win- 
dows, jsapi.sh per Linux. Una cosa molto importan- 
te per l'esecuzione corretta del programma è il pas- 
saggio del parametro u -mx312m" alla Virtual Machi- 
ne di Java. Con questo parametro riserviamo abba- 
stanza memoria al nostro programma. Infatti facen- 
do partire lo stesso programma senza questo para- 
metro andremo sicuramente ad incappare in un 
errore di memoria. Nella directory del nostro pro- 
gramma dovremo inoltre inserire i file della presen- 
tazione. Per questo programma sono stati definiti 
staticamente nel codice, ma possiamo anche imma- 
ginare di far partire il programma passando come 
parametro una directory e ricavare dinamicamente i 
file che servono (immagini e testo). Una volta avvia- 
ta dobbiamo soltanto godere di questo gioiellino 
tecnologico, andando avanti e indietro tra le slide. 



CONCLUSIONI 

Le applicazioni che possiamo sviluppare grazie al ri- 
conoscimento vocale sono tantissime. Ad esempio, 
pur non avendo alcun tool relativo al suo interno, 
Sphinx4 potrebbe essere la base di partenza per scri- 
vere un programma per il riconoscimento vocale 
delle persone, attraverso lo spettro della voce. Inol- 
tre se pensiamo ad un nostro programma che utiliz- 
za Sphinx4 insieme ad un sintetizzatore vocale, co- 
me ad esempio FreeTTS, vediamo un'applicazione 
che capisce cosa viene detto e magari risponde. Il 
punto dolente è la definizione di un dizionario per- 
sonalizzato, per il quale vi rimando al sito di Sphinx4 
dove c'è un'esauriente documentazione al riguardo. 
Per il resto buon divertimento con questo utile (e 
soprattutto opensource) framework. 

Federico Paparoni 



► 20 /Aprile 2005 



http://www.ioprogrammo.it 



IOPROGRAMMO WEB T I Usare GetText per creare applicazioni multilingua 



Applicazioni multilingua con PHP 



In che lingua te 



lo dico? 



Viviamo nell'era globale. Le nostre applicazioni soprattutto se 
orientate al Web devono risultare portabili non solo da un sistema 
all'altro ma anche da una lingua all'altra, scopriamo come fare! 




Utilizza questo spazio per 
le tue annotazioni 



JO 




REQUISITI 



Conoscenze richieste 



Principi di PHP 



PHP 5 



^^ ■._-! .1 J 



Tempo di realizzazione 



y\ y\(y\ 



Inutile che io dica a voi, esperti navigatori di In- 
ternet, che viviamo nell'era del villaggio globale. 
Ormai lo sapete benissimo, non conta se svilup- 
pate per l'Italia, per l'America e perché no per la Ci- 
na! Conta invece quanto la vostra applicazione può 
essere facilmente utilizzata in ciascuno di questi 
paesi senza che voi dobbiate riprogrammarla per 
renderla fruibile in ciascuna delle lingue parlate in 
questi paesi. Detto in parole povere, se volete avere 
una minima possibilità di diffondere le vostre appli- 
cazioni al di fuori del mercato locale, dovrete pro- 
gettarle in modo che siano localizzabili in qualsiasi 
lingua. Detto questo, e senza dilungarci troppo, nei 
grandi vantaggi economici/ commerciali di cui può 
godere un'applicazione pronta per essere facilmen- 
te esportata, è il caso di capire come questo prodi- 
gio possa avvenire. 



CONOSCETE IL CINESE? 

Ho il dubbio che molti programmatori non cono- 
scano il tedesco, allo stesso modo ho il dubbio che 
una buona parte non conosca neanche l'Inglese, 
volendo poi esaminare qualcuna delle altre possi- 
bilità sconfineremmo nella certezza, qualcuno 
conosce il Cinese? Detto questo è importante sta- 
bilire che non dobbiate essere voi a tradurre le 
vostre applicazioni, ma che piuttosto debba essere 
reso disponibile a chiunque una sorta di Kit che, in 
modo semplice e senza per questo dover conosce- 
re una riga di programmazione, metta in grado di 
tradurre un'applicazione senza doverla riprogram- 
mare/ricompilare o in qualche modo mettere 
mano al codice. 

Riepilogando, la nostra applicazione multilingua 
dovrà essere composta in tre strati 

Applicazione Base -> interprete -> vocabolario 



molto semplicemente l'interprete sarà una mini- 
applicazione che prenderà le stringhe che caratte- 
rizzano la versione base, le confronterà con un vo- 
cabolario contenente stringhe in lingua straniera e 
produrrà un output nella lingua opportuna. 

Applicazione Base contiene la stringa: "Questo arti- 
colo è fantastico" 

Vocabolario Italiano contiene: "Questo articolo è fan- 
tastico" ->"This article is beatiful" 

L'interprete controlla se nel vocabolario inglese c'è 
una stringa opportuna rispetto a quella base e se c'è 
la utilizza per fornire all'utente la versione nella lin- 
gua desiderata. Il meccanismo sembra molto sem- 
plice ed ha alcuni interessanti vantaggi. Infatti posto 
che venga diffuso un vocabolario delle stringhe ba- 
se, chiunque ne fosse capace potrebbe produrre le 
corrispondenti stringhe in una lingua straniera. Ba- 
sterebbe poi settare una qualche variabile di confi- 



DA DOVE INIZIARE 



PHP deve essere com- 
pilato con il supporto 
a GetText. Se installa- 
te PHP da una distri- 
buzione linux, potete 
semplicemente scari- 
care il modulo corret- 
to da uno dei reposi- 
tory della distribuzio- 
ne. Viceversa in 
ambiente Windows 
potete semplicemen- 
te decommentare il 
commento che riguar- 
da gettext all'interno 
del PHP.ini. E' impor- 
tante dotarsi di tutto 



il software necessario 
per creare dei voca- 
bolari. Al solito in 
ambiente linux tutto 
é presente in modo 
abbastanwa autono- 
mo, semplicemente 
installando il pacchet- 
to che contiene get- 
text nella vostra 
distribuzione. In 
ambiente Microsoft 
potete scaricare e 
installare tutto da 
http://gettext.sour- 
ceforge.net 



► 22 /Aprile 2005 



http://www.ioprogrammo.it 



Usare GetText per creare applicazioni multilingua ■ T IOPROGRAMMO WEB 



gurazione nel programma, per mostrare l'interfaccia 
del software nella lingua desiderata. Va da se che a 
questo punto sorge qualche piccolo problema. Il 
primo problema riguarda la scrittura dell'interprete. 
Il secondo problema riguarda il formato del vocabo- 
lario. Chiaramente l'interprete e il vocabolario sono 
due strumenti molto legati fra loro. L'interprete deve 
conoscere infatti il formato in cui è strutturato il vo- 
cabolario per poterlo utilizzare. A questo punto si 
possono seguire due strade: 

1. Ideare un proprio formato di vocabolario perso- 
nalizzato e poi programmare un apposito inter- 
prete 

2. Utilizzare un qualche formato specifico possibil- 
mente standard e sfruttare un interprete ade- 
guato già esistente per questo formato. 

poiché siamo amanti degli standard noi seguiremo 
questa seconda strada. Prima di parlare di come sarà 
fatto il nostro vocabolario, è però corretto definire 
alcune proprietà che vorremmo che avesse. In parti- 
colare il nostro vocabolario deve essere poter utiliz- 
zato da chiunque conosca una lingua straniera di- 
versa da quella in cui abbiamo programmato l'ap- 
plicazione, dunque deve essere semplice! Non ne- 
cessariamente sarà usato da un programmatore, 
piuttosto sarà usato da un traduttore, perciò dovre- 
mo fornirgli una comoda applicazione facile facile 
da usare, senza troppi fronzoli. In secondo luogo il 
nostro vocabolario dovrà essere portabile. Dovrà es- 
sere utilizzato sia con Windows che con Linux. Infine 
vorremmo che il nostro vocabolario non sia legato 
alla scelta di un linguaggio di programmazione. In 
realtà semplicemente cambiando l'interprete ma la- 
sciando invariato il formato del vocabolario, esso 
potrebbe essere utilizzato con applicazioni scritte in 
PHP ma anche in Delphi, o in Visual Basic, C++ e 
quant' altro. Per tutti questi motivi, la nostra scelta ri- 
cade su un prodotto OpenSource chiamato GetText. 



SIETE PRONTI 



GetText è un progetto elaborato da GNU, perciò de- 
cisamente OpenSource. Tutta la documentazione 
sul progetto è reperibile all'indirizzo http://www 
.gnu.org/software/gettext/. Quasi tutto il software 
OpenSource multilingua in circolazione sfrutta Get- 
Text. Il vocabolario utilizzato da applicazioni proget- 
tate secondo GetText è un normale file di testo! Il che 
lo rende estremamente portabile e utilizzabile da 
chiunque. È anche vero che nel tempo sono state 
sviluppate applicazioni molto semplici per gestire in 
modo visuale un vocabolario GetText, come ad 
esempio PoEdit - http://www.poedit.com - per cui è 
facilmente intuibile che un eventuale traduttore può 



utilizzare queste applicazioni per generare o modifi- 
care un vocabolario GetText. Infine GetText è utiliz- 
zabile sia sotto Linux che sotto Windows, e con tutti 
o quasi tutti i linguaggi attualmente disponibili. In 
questo articolo utilizzeremo PHP in ambiente Linux, 
e di volta in volta spiegheremo anche come e dove 
reperire i tool per compiere gli stessi passi in am- 
biente Windows. 



IL PRIMO PROGRAMMA 



Al solito il miglior modo per capire qualcosa di quel- 
lo che fin qui abbiamo accennato in maniera teorica 
è dare uno sguardo ad un esempio: 

$language="it_IT"; 

putenv("LANG=$language"); 

setlocale(LC_ALL,$language); 



$domain = 'messages'; 



bindtextdomain($domain / "/home/jaco/languages"); 
textdomain($domain); 



$stringa=gettext(" Hello World"); 



echo $stringa; 

La prima funzione interessante di questo esempio è 
la funzione "seilocaleQ". Con questa funzione si può 
indicare a PHP che alcune particolari stringhe devo- 
no essere formattate secondo una lingua piuttosto 
che un'altra. Considerate ad esempio il classico: 

echo strftime("%A %e %B %Y", mktime( 

0, 0, 0, 03 27, 2005)); 

restituisce: Sunday 27 March 2005 

invece la forma: 

$language="it_IT"; 

setlocale(LC_ALL,$language); 

echo strftime("%A %e %B %Y", mktime( 

0, 0, 0, 03, 27, 2005)); 

restituisce: domenica 27 marzo 2005 

Cioè con le stringhe correttamente formattate in ita- 
liano. A questo punto seguono alcune righe decisa- 
mente più interessanti 

$domain = 'messages'; 

bindtextdomain($domain,"/home/jaco/languages"); 
textdomain($domain); 
$stringa=gettext("Hello World"); 

con la seconda e terza riga informiamo PHP che i 
nostri vocabolari saranno contenuti in una gerar- 
chia al di sotto del percorso /home/jaco/languages, 




IL SOFTWARE 
POEDIT 

Manipolare i 
vocabolari é 
abbastanza semplice. 
D'altra parte come 
abbiamo già visto si 
tratta di semplici file 
di testo, tuttavia se 
volete dotare i vostri 
traduttori di 
un'applicazione che li 
astragga 

completamente dal 
formato utilizzato nei 
vocabolari, potete 
allora usare poedit, un 
software specifico con 
il formato utilizzato da 
gettext e reperibile 
all'indirizzo 
http://sourceforge.net/ 
projects/poedìtl 



http://www.ioprogrammo.it 



Aprile 2005/ 23 ► 



IOPROGRAMMO WEB T I Usare GetText per creare applicazioni multilingua 





APPROFONDIMENTI 



GETTEXT E IL 

SOFTWARE 

OPERI SOURCE 

GetText é il metodo 

usato dalla maggior 

parte dei software 

OpenSource oggi 

disponibili. La 

maggior parte delle 

applicazioni Open 

Source sono scritte 

utilizzando GetText 

come sistema per la 

gestione delle lingue. 

Data la grande 

diffusione 

dell'OpenSource si 

tratta di un indicatore 

piuttosto valido 

dell'utilità di questyo 

sistema. 



inoltre i file che contengono i vocaboli sarnno chia- 
mati messages.po. Infine con la funzione gettext si 
avvia il processo di traduzione. Gettext controlla se 
nel vocabolario it_IT definito in setlocale c'è una 
stringa corrispondente a Hello World, se c'è riempie 
il contenuto della variabile $stringa con la traduzio- 
ne adeguata. Il meccanismo non è complesso. Si 
tratta veramente di poche istruzioni. Perciò il nostro 
problema adesso è creare il vocabolario. 



CREARE 

IL VOCABOLARIO 

Il punto di partenza è sempre il file index.php esat- 
tamente come l'abbiamo creato in precedenza, e 
cioè: 



<? 

$language="it_IT"; 

setlocale(LC_ALL,$language); 

echo strftime("%A %e %B %Y", mktime( 

0, 0, 0, 03, 27, 2005)); 

$domain = 'messages'; 

bindtextdomain($domain,"/home/jaco/languages"); 

textdomain($domain); 



$stringa=gettext("Hello World"); 



echo $stringa; 



?> 



a questo punto usiamo il comando xgettext come 
segue: 

xgettext -n index.php 

se siete in ambiente Linux dovreste avere già tutto 
installato nel momento in cui avete installato il pac- 
chetto contenente gettext, viceversa se siete in am- 
biente Windows, trovate tutto quello che vi occorre 
alla uri http://gettext.sourceforge.net. Il risultato del- 
l'esecuzione di questo comando è un file message 
.pò. Un normale file di testo che contiene le seguen- 
ti definizioni: 

# SOME DESCRIPTIVE TITLE. 

# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT 
HOLDER 

# This file is distributed under the same license as the 
PACKAGE package. 

# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 

# 

#, fuzzy 

msgid "" 

msgstr "" 

"Project-Id-Version: PACKAGE VERSION\n" 

"Report-Msgid-Bugs-To: \n" 

"POT-Creation-Date: 2005-02-28 ll:01+0100\n" 
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 



"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 

"Language-Team: LANGUAGE < LL@li.org >\n" 

"MIME-Version: 1.0\n" 

"Content-Type: text/plain; charset=CHARSET\n" 
"Content-Transfer-Encoding : 8bit\n" 



#: index.php:8 



msgid "Hello World" 



msgstr "" 

Le ultime due righe sono esplicative. Forniamo una 
traduzione per l'italiano modificando il file come 
segue: 

# SOME DESCRIPTIVE TITLE. 

# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT 
HOLDER 

# This file is distributed under the same license as the 
PACKAGE package. 

# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 

# 



msgid "" 



msgstr "" 



"Project-Id-Version: PACKAGE VERSION\n" 



"Report-Msgid-Bugs-To: \n" 



"POT-Creation-Date: 2005-02-28 ll:01+0100\n" 
"PO-Revision-Date: 2005-02-28 ll:13+0100\n" 

"Last-Translator: jaco <jaco@jaco.it>\n" 

"Language-Team: LANGUAGE < LL@li.org >\n" 
"MIME-Version: 1.0\n" 



"Content-Type: text/plain; charset=CHARSET\n" 
"Content-Transfer-Encoding : 8bit\n" 



#: index.php:8 



msgid "Hello World" 



msgstr "Ciao Mondo" 

Ed anche in questo caso le ultime due righe sono 
significative. Ci mancano ancora due passi per fina- 
lizzare il tutto. Il primo passo è compilare il file mes- 
sages.po. Niente di più facile, il comando è: 

msgfmt messages.po 

questo comando da luogo a un file messages.mo 
che altro non è che la versione compilata di messa- 
ges.po. L'ultimo passo è creare una struttura su file 
system in grado di ospitare i file fin qui creati. 
Ricordiamo che abbiamo usato: 

bindtextdomain($domain/7home/jaco/languages"); 

quindi va da se che questa struttura che il nostro 
punto di partenza sarà /home/jaco/languages. 
Il resto della struttura va creato secondo la regola 
generale <DOMAIN>/<LANG_CODE>/LC_MESSA- 
GES/* .mo dove <DOMAIN> è il percorso che abbia- 
mo dichiarato richiamando la funzione bindtextdo- 
main. Per cui la struttura delle directory che ci con- 
sente di usuffruire delle funzioni offerte da gettext è 



► 24 /Aprile 2005 



http://www.ioprogrammo.it 



Usare GetText per creare applicazioni multilingua ■ T IOPROGRAMMO WEB 



la seguente: 



"Project-Id-Version: PACKAGE VERSION\n" 
"Report-Msgid-Bugs-To: \n" 



/home/jaco/languages/it_IT/LC_MESSAGES/messages.mo "POT-Creation-Date: 2005-02-28 12:Ql+01QQ\n" 



dove messages.mo è il file che abbiamo compilato in 
precedenza. Provate a puntare il browser adesso su 
http://localhostlindex.php - adeguando ovviamente 
al percorso utilizzato sul vostro webserver - e otter- 
rete: 

domenica 27 marzo 2005 
Ciao Mondo 



"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 

"Language-Team: LANGUAGE <LL@li.org>\n" 

"MIME-Version: 1.0\n" 

"Content-Type: text/plain; charset=CHARSET\n" 
"Content-Transfer-Encoding : 8bit\n" 



#: paperino.php:7 



msgid "ioProgrammo the best magazine of the worid" 
msgstr 




tuttavia è sufficiente modificare index.php come se- 
gue 



<? 



$language="en"; 



setlocale(LC_ALL,$language); 



echo strftime("%A %e %B %Y", mktime( 
0, 0, 0, 03, 27, 2005))."<br>" 



$domain='messages'; 



bindtextdomain($domain/7home/jaco/languages"); 



textdomain($domain); 



$stringa=gettext("Hello World"); 



echo $stringa; 



?> 



per ottenere di nuovo 

Sunday 27 March 2005 
Hello World 



COMPLICHIAMOCI 
UHI PO LA VITA 

Creiamo un secondo file paperino.php composto 
come segue: 



<? 

$language="it_IT"; 

setlocale(LC_ALL,$language); 

$domain='messages'; 

bindtextdomain($domain/'/home/jaco/languages"); 

textdomain($domain); 



$stringa=gettext("ioProgrammo is the best magazine 

of the worid"); 



echo $stringa; 



?> 



Copiamo il messages.po che abbiamo ottenuto in 
precedenza in un file old.po ed eseguiamo xgettext - 
n paperino.php, otteniamo un file messages.po com- 
posto come segue: 



# SOME DESCRIPTIVE TITLE. 



possiamo motificarlo aggiungendo la traduzione 
u ioProgrammo la migliore rivista del mondo" nel 
campo msgstr ma a questo punto ci troviamo di 
fronte ad un enigma. Abbiamo cioè due file, old.po 
e messages.po ognuno ha dentro delle stringhe che 
possono servirci, ma quale dei due usare? Dobbia- 
mo trovare un modo di unificare i due file senza 
perdere le modifiche fin qui ottenute. Niente di più 
facile. 
Il comando da usare è : 

msgmerge messages.po old.po -output-file=new.po 

questo comando genera un file che miscela i due 
ottenuti in precedenza, e il cui contenuto è il 
seguente: 

[■■■] 

# This file is distributed under the same license as the 
PACKAGE package. 

# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 

# 

msgid "" 



msgstr "" 



"Project-Id-Version: PACKAGE VERSION\n" 



"Report-Msgid-Bugs-To: \n" 



"POT-Creation-Date: 2005-02-28 ll:01+0100\n" 
"PO-Revision-Date: 2005-02-28 12:03+0100\n" 

"Last-Translator: jaco <jaco@jaco.it>\n" 

"Language-Team: LANGUAGE <LL@li.org>\n" 

"MIME-Version: 1.0\n" 

"Content-Type: text/plain; charset=CHARSET\n" 
"Content-Transfer-Encoding : 8bit\n" 

#: index.php:8 

msgid "Hello World" 

msgstr "Ciao Mondo" 

msgid "ioProgrammo the best magazine of the worid" 

msgstr "ioProgrammo la migliore rivista del mondo" 



[-] 



non ci resta che compilare il file appena ottenuto 
con msgfmt new.po e copiare il file messages.mo 
così ottenuto nella directory corrispondene ed il 
gioco è fatto. 

Otterremo un unico vocabolario che serve due 
file .php 




APPROFONDIMENTI 



LE FONTI UFFICIALI 

GetText é un sistema 
piuttosto complesso 
che tiene conto di un 
gran quantitativo di 
variabili, che vanno 
dalla gestione 
dell'output delle date a 
quello dei caratteri 
speciali. Non era 
ovviamente possibile 
trattare tutti questi 
aspetti all'interno di 
questo articolo, che 
tuttavia rimane 
sufficiente per iniziare 
a sviluppare le vostre 
applicazioni 
multilingua. Il sito 
ufficiale dove reperire 
informazioni specifiche 
in relazione a qualche 
particolare problema é: 
http://www.gnu.org/sof 
tware/gettext 



http://www.ioprogrammo.it 



Aprile 2005/ 25 ► 



IOPROGRAMMO WEB T Un sito conforme al pattern MVC 



Come costruire applicazioni web utilizzando STRUTS 

Java e Struts 
i belli del Web 

Vi spieghiamo come creare applicazioni Web conformi al modello 
MVC che ci consente di separare la logica dell'applicazione dalla sua 
grafica di presentazione 




Ci CD □ WEB 

Struts.zip 



VL 




I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



REQUISITI 



■w.i.i.wmiw.m4fl 

Principi di Java 




Struts è un nome di battesimo decisamente ori- 
ginale per un framework; è impossibile quindi 
non chiedersi: "come si pronuncia?", ma so- 
prattutto: "cosa significa? ". Alla prima domanda non 
vi è risposta certa. Nel mio ufficio l'ho sentito pro- 
nunciare nei modi più originali: "struz, stmz", anche 
se la fonetica esatta pare sia stmz. La seconda 
domanda invece, ha una risposta decisamente 
meno "randomica", Babylon in merito al suo signifi- 
cato suggerisce: "si pavoneggia, andature impettite". 
A quanto pare, abbiamo a che fare con un frame- 
work impronunciabile ma decisamente superbo! 
Per esperienza acquisita nell'utilizzo, vi assicuro che 
la sua superbia è del tutto fondata; utilizzare Struts 
presenta moltissimi vantaggi e pochissimi svantag- 



COME INIZIARE 



BI^SS[ 



Tempo di realizzazione 



MfVHYl (VI 



Prima di tutto c'è bi- 
sogno di un JDK re- 
cente. Poi ovviamen- 
te c'è bisogno del fra- 
mework struts. Infine 
c'è bisogno deW'Ap- 
plìcatìon server Tom- 
cat. Un componente 
opzionale è l'ambien- 
te di sviluppo eclipse. 
Trovate tutto nel CD 
allegato alla rivista, o 
ovviamente sui ri- 
spettivi siti d'origine. 
Diamo per scontato 
che abbiate installato 
sia il JDK che Tomcat. 
L'installazione di 
struts è relativamen- 
te semplice, è suffi- 
ciente scompattare il 
file contenente il pac- 
chetto e copiare tutti 



i file jar nella direc- 
tory WEB-INFI, i file 
.tld andranno invece 
nella directory WEB- 
INFIIib. Sarà necessa- 
rio poi configurare il 
file web.xml e il file 
struts-confìg.xml se- 
condo una certa logi- 
ca che tratteremo in 
modo approfondito 
all'interno dell'artico- 
lo. Molto brevemente 
il file web.xml con- 
terrà le informazioni 
relative a chi dovrà 
servire le richieste 
dell'applicazione, 
mentre il file struts- 
config.xml conterrà 
informazioni relative 
a come la richiesta 
debba essere gestita. 



gi, tutto questo a costo zero. Bene, dopo questa bre- 
ve parentesi introduttiva, quasi pubblicitaria oserei 
dire, proseguiamo la nostra lettura alla scoperta di 
Struts, e soprattutto prepariamoci a costruire la no- 
stra prima applicazione web basata su di esso. 



COS'È STRUTS 
E SOPRATTUTTO 
A COSA SERVE 

Struts è un framework gratuito sviluppato dalla Apa- 
che Jakarta Project Group, che consente di utilizzare 
al meglio, all'interno di una applicazione web (basa- 
ta su J2EE), il pattern MVC (model, view, controller). 



COS'È E A COSA SERVE 
IL PATTERN MVC 

Il pattern MVC viene utilizzato per separare, all'in- 
terno di una generica applicazione, la parte di Busi- 
ness Logic (Model), la parte di Interfaccia Utente 
(View) e la parte di Program Progression (Controller). 
Esso è composto da tre componenti principali: 

• Model: il modello, si occupa della definizione 
delle informazioni, quindi rappresenta i dati nel 
sistema. 

• View: La vista, rappresenta l'interfaccia utente, 
come i dati sono rappresentati all'utente. 

• Controller: Il "meccanismo di controllo", si oc- 
cupa di verificare il flusso e lo stato dei dati inse- 
riti dall'utente. Favorisce lo scambio di dati tra 
Model e View. 

Ad oggi, l'utilizzo del pattern MVC è molto diffuso ed 



► 26 /Aprile 2005 



http://www.ioprogrammo.it 



Un sito conforme al pattern MVC ■ T IOPROGRAMMO WEB 



i vantaggi che presenta sono effettivamente nume- 
rosi: 

• Consente di separare la parte di business rules 
dalla presentation, favorendo così la modularità 
dei componenti. 

• Chi sviluppa il front- end (view), non ha bisogno 
di sapere come queste pagine verranno popola- 
te (mediante il model). 

• È possibile, mediante il Controller, gestire la vi- 
sualizzazione dei dati in maniera dinamica. 
View diverse per utenti diversi, più View per lo 
stesso utente, ecc.. 

• È possibile centralizzare la sicurezza dell'appli- 
cazione all'interno del Controller. Con il pattern 
MVC, l'interfaccia verso l'utente viene fatta pas- 
sare solo attraverso l'oggetto controller, questo 
rappresenta quindi l'unico punto d'accesso e co- 
me tale l'unico punto in cui vanno effettuati tutti 
i controlli di sicurezza. 



STRUTS 

E IL CONTROLLER 

Il controller, come già abbiamo accennato, all'inter- 
no di un'applicazione MVC svolge diverse funzioni, 
tra queste ha l'onere di ricevere input dal client, in- 
vocare una o più operazioni appartenenti alla logica 
dell'applicazione e gestire la risposta da restituire al 
client. In Struts, gli oneri nel controller, sono gestiti 
tramite vari componenti, uno di questi è rappresen- 
tato da un'istanza della classe orgapache.struts.ac- 
tionActionServlet. La suddetta classe, estende la 
classe javax.servlet.http.HttpServlet e si occupa di 
gestire, a fronte di una richiesta HTTR il giusto rein- 
dirizzamento all'interno del framework. 
Detto in soldoni riceve una richiesta da parte di un 
client e stabilisce chi la deve gestire a seconda della 
tipologia di richiesta. 

È importante sapere che va configurata all'interno 
del file: web.xml (descrittore di deploy di una gene- 
rica applicazione web). La sua configurazione verrà 
descritta in seguito. 

Riassumendo, la classe ActionServlet, "decide" (a 
fronte di una richiesta HTTP), quale classe dovrà 
soddisfare la richiesta effettuata dal client. La classe 
"prescelta", viene definita helper; questa sa esatta- 
mente quale operazione deve svolgere per soddisfa- 
re la richiesta del client. Nel framework Struts, que- 
sta classe deriva dalla classe org.apache.struts.action 
Action. 



IL FILE WEB.XML 

Sebbene questo file sia generico per la configurazio- 
ne di tutte le applicazioni web, ci sono delle opzioni 



di configurazione specifiche per Struts. Un esempio 
di file web.xml potrebbe essere il seguente: 

<web-app id="StrutsWebApp"> 

<servlet> 

<servlet-name>action</servlet-name> 
<servle-class> 

org.apache.struts.action.ActionServIet 

</servlet-class> 

</servlet> 

</web-app> 

Con queste righe di configurazione abbiamo detto 
che tutte le richieste HTTP fatte all'applicazionede- 
vono essere gestite dalla classe orgapache.struts.ac- 
tionActionServlet. Questa classe come già detto as- 
solverà al ruolo di controller. 

<web-app id="StrutsWebApp"> 

<servlet> 

</servlet> 

<servlet-mapping> 

<servlet-name>action</servlet-name> 

<url-pattern>*.do</url-pattern> 

</servlet-mapping> 

</web-app> 

Queste righe indicano che solo le richieste effettua- 
te a pagine con estensione *.do devono essere gesti- 
te dalla classe org.apache.struts.actionActionServlet. 
Utilizzando questo approccio si possono eventual- 
mente fare convivere in una stessa web application 
pagine gestite con struts e pagine gestite in modo 
tradizionale. 



LA CLASSE 
ACTIONSERVLET 

Rappresenta un'estensione del componente Con- 
troller. Il suo compito è quello di "mettere in moto" la 
logica di Business dell'applicazione a fronte di una 
richiesta client. La classe Action può svolgere diver- 
se funzioni e contenere diversi metodi, ma il quello 
più importante in assoluto, è: executeQ. Questo vie- 
ne richiamato dal controller a fronte di una request 
proveniente dal client. È importante sapere che que- 
sto metodo restituisce un oggetto di tipo orgapa- 
che.struts.actionActionForward. 
Esso determina una destinazione verso la quale il 
controller può inviare il controllo al termine della 
Action. I forward delle azioni, come le Action da ri- 
chiamare, vengono definiti nel file di configurazione 
messo a disposizione da struts: struts-configxml. 
Un esempio di file config.xml potrebbe essere il se- 
guente: 

<action path = "/showl_istaProdotti" type= 




COS'È UNA WEB 
APPLICATION 

Una Applicazione web 
basata su J2EE è un 
insieme di servlet, jsp, 
pagine html, classi ed 
altre risorse che 
collegate tra di loro, 
creano una 
applicazione web 
completa Questa può 
essere installata ed 
eseguita (in maniera 
concorrente) da web 
container multipli. Per 
motivi "contestuali" la 
definizione di 
applicazione web è 
poco esaustiva, per chi 
avesse ancora dei 
dubbi si consiglia uno 
studio un po' più 
approfondito mediante 
altre fonti. 

http://java.sun.eom/j2ee/1 . 
4/docs/tutorial/doc/index. 
html 



http://www.ioprogrammo.it 



Aprile 2005/ 27 ► 



IOPROGRAMMO WEB T Un sito conforme al pattern MVC 




"web.ShowListaProdottiAction" scope="session"> 



</action> 

Abbiamo "mappato" l'azione IshowListaProdotti con 
la Action web.ShowListaProdottiAction. Questo si- 
gnifica che ogni volta che il controller riceverà una 
request che nell'URI contiene la stringa "IshowLi- 
staProdotti" verrà richiamato il metodo executeQ 
della classe web.ShowListaProdottiAction. 

oction path = "/showl_istaProdotti" type= 

"web.ShowListaProdottiAction" scope="session"> 

<forward name="error" path="/Home.jsp"></forward> 

<forward name="ok" path = 
"/showListaProdotti.jsp"></forward> 



</action> 



strato business. Come avviene questo passaggio di 
dati? Il framework preleva automaticamente i dati 
dalla request, li passa alla Action utilizzando un og- 
getti di tipo ActionForm. 

Il mapping tra Action e ActionForm viene sempre 
definito nel file di configurazione: struts-config.xml. 
In pratica data una form HTML dobbiamo capire 
come il passaggio dei dati viene effettuato verso la 
action che esaudirà la richiesta. Per farlo abbiamo 
bisogno di creare una classe che estenda la Action- 
Form, recuperi i dati e una volta validati li spedisca 
alla action che deve gestirli. Il tutto viene fatto anco- 
ra una volta nel file struts-config.xml, ad esempio: 

oction path=7showl_istaProdotti" name=" 

ShowListaProdottiForm" scope="session"> 

</action> 



L'azione "IshowListaProdotti" definisce due forward: 
<forward nome- "error"> e forward: <forward name- 
"ok">, questo significa che: se il metodo executeQ, 
restituisce un ActionForward = "errofX applicazione 
visualizzerà la pagina: "Home.jsp", se invece restitui- 
sce un ActionForward - "o k" L'applicazione visualiz- 
zerà la pagina showListaProdotti.jsp. 
Riepilogando, nel file web.xml viene specificato che 
tutte le richieste di una pagina .do devono essere ge- 
stite dalla classe struts-config.xml e richiama il me- 
todo executeQ della classe preposta a servire la ri- 
chiesta. Il metodo executeQ restituisce un forward 
che può essere utilizzato per passare il controllo a 
una pagina terza, nel nostro caso è stato utilizzato 
per produrre un output di errore o esito positivo. 
Tutta questa procedura riassume il concetto di 
"Controller". Le azioni eseguite dalle classi che gesti- 
scono le richieste esauriscono invece il concetto di 
"Model" 



IL MODELLO 

La collocazione di questo componete in Struts (ma 
in generale un tutte le applicazioni web), non è così 
banale. In generale, il confine che separa gli oggetti 
della logica di Business da quelli della presentazione 
è sempre molto sottile e varia a seconda delle esi- 
genze di ogni singola applicazione. In ogni caso, la 
"regola" della buona programmazione, suggerisce di 
mantenere gli oggetti Business della logica dell'ap- 
plicazione, separati dalla presentazione. Il motivo è 
pressoché ovvio, in questo modo, se si decide di 
cambiare la grafica dell'applicazione ci risparmiamo 
di cambiare anche gli oggetti di Business! In Struts il 
componente model, si può identificare con un'istan- 
za della classe: orgapache.struts.actionActionForm. 
Gli oggetti ActionForm, hanno la stessa funzione che 
può avere un comune oggetto formBean, e cioè, si 
occupano di passare i dati dallo strato client, allo 



<form-beans> 



<form-bean name= "ShowListaProdottiForm" 
type="web.ShowListaProdottiAction"> 



</form-bean> 



</form-beans > 



LA VISTA 

Per questo ultimo componente, in realtà, non c'è 
molto da dire, come in una qualsiasi applicazione 
web basata su J2EE, anche in Struts si identifica me- 
diante: pagine HTLM, Servlet, ]SP, tag Custom ecc.. 
In Figura 1 è mostrato dove si colloca Struts in una 
tipica applicazione web Tree tiers. 





Client Tier 






Web 
Btowse 











Html 
Http 



Middle Tier 




Framework 
Struts 

(HTML, JSP, 
Servlet, XML) 


Web Container 




Fig. 1: Dove si colloca Stuts all'interno di una appli- 
cazione Tree tiers 



IL CARRELLO 
DELLA SPESA 

Arrivati a questo punto, i veri programmatori, saran- 
no già stanchi di tutte queste chiacchiere e saranno 
sicuramente ansiosi di cominciare a sviluppare. 
Bene, come non accontentarli? 
Partiamo quindi con lo sviluppo della nostra prima 
applicazione web basata su Struts: "Carrello della 
spesa" Se vi piace il suo nome siete già a buon punto!! 
Cosa ci consente di fare questa applicazione? 
Beh, dal suo nome si evince che ci consente di com- 
prare qualcosa. Sarà presente una prima schermata 
iniziale dove è possibile scegliere i prodotti d'acqui- 



► 28 /Aprile 2005 



http://www.ioprogrammo.it 



Un sito conforme al pattern MVC ■ T IOPROGRAMMO WEB 



stare. Mediante dei pulsanti di navigazione è possi- 
bile compiere un'intera procedura d'acquisto: 

• 1 . - Scegli i prodotti e inseriscili in un carrello vir- 
tuale. 

• 2. - Visualizza il carrello e conferma l'acquisto. 

• 3. - Inserisci i dati per l'Acquisto. 

• 4. - ACQUISTA!! 



IL WORK FLOW 
DELL'APPLICAZIONE 

La nostra applicazione: "Carrello della spesa" e com- 
posta da diversi "componenti" e la sua struttura può 
essere riassunta in: Figura 2. 




Fig. 2: Struttura dell'applicazione web 

Tenendo ben presenta questo diagramma, comin- 
ciamo ad analizzare il work flow di Struts in relazio- 
ni ai suoi componenti. 

La prima Action che viene richiamata all'avvio del- 
l'applicazione, è la initialdo, questa a sua volta 
richiama la index.do che effettua un forward diretta 
alla Main.jsp. 
Quindi Ricapitolando: 

startApplication -> initial.do -> index.do -> Main.jsp 

Siamo così arrivati alla prima jsp (Main.jsp) presen- 
te nel nostro diagramma di riferimento. 
Questa pagina presenta una sintassi molto sempli- 
ce, il suo unico compito è quello di creare il frameset 
che conterrà la nostra applicazione, e di richiamare 
(all'interno di un frame) la showListaProdotti.do. 
Di seguito riportiamo un "pezzo" significativo della 
pagina in questione: 

<frameset> 

<frame name="header" src="showl_istaProdotti.do"> 
</frameset> 

Facile no?? Rispecchia perfettamente quanto detto 
sopra!! Ma proseguiamo la nostra analisi, scoprendo 
quale cataclisma si verifica nel modo web quando si 



richiama la: showListaProdotti.do. 

<action path = "/showl_istaProdotti" type= 

"dae.ShowListaProdottiAction" name= 
"showListaProdottiForm" scope= 

"session" validate="false"> 

<forward name="success" path = 

"/ShowListaProdotti.jsp"> 

</forward> 
</action> 

Il frammento di struts- config.xml relativo alla action 
showListaProdotti, ci dice che: 

La showListaProdotti.do, crea una istanza (se già non 
esiste) della showListaProdottiForm,successivamen- 
te richiama la ShowListaProdottiAction che con un 
forward name=" success" richiama la ShowListaPro- 
dotti.jsp. Anche questa operazione descritta in tre ri- 
ghe appare decisamente semplice, ma addentria- 
moci nei componenti Struts in questione, e vediamo 
cosa accada al loro interno. 

Componente model 

Il modello ShowListaProdottiForm rappresenta uno 
dei model dell'applicazione, al sui interno viene 
semplicemente istanziato un ArrayList che conterrà 
tutti i prodotti disponibili per l'acquisto. 

Componente controller 

All'interno del controller ShowListaProdottiAction, 
precisamente nel metodo executeQ, viene: 

• Recuperata un'istanza deR'ActionForm. 

• Creata, mediante la classe CarrelloDBQ, la lista 
dei prodotti disponibili per l'acquisto. 

• Popolato FArrayList dello ShowListaProdotti- 
Form, con i prodotti disponibili per l'acquisto. 

• Eseguito il findForward alla pagina: ShowLista- 
Prodotti.jsp 

Ecco l'implementazione del metodo: 

public Action Forward execute(ActionMapping mapping, 
ActionForm form, HttpServIetRequest request, 

HttpServIetResponse response) 

{ ShowListaProdottiForm prodottiForm = 

(ShowListaProdottiForm)form; 

CarrelloDB model = CarrelloDB.getQ; 

ArrayList prodotti = model.creaProdottiQ; 

prodottiForm.setListaProdotti(prodotti); 

return mapping .findForward("success"); 



È importante notare che: 

• Non si crea una nuova istanza dello ShowLista- 
ProdottiForm, ma viene preso e "castato" quello 




http://www.ioprogrammo.it 



Aprile 2005/ 29 ► 



IOPROGRAMMO WEB T Un sito conforme al pattern MVC 




passato al metodo executeQ. Il "tipo specifico" di 
form e quello definito nello struts-confìg.xml 

La classe CarrelloDBQ, è la classe dove avvengo- 
no tutte le operazioni di creazione e salvataggio 
dei dati. Per questa ultima funzionalità può va- 
gamente rappresentare una simulazione di un 
DB. 



LA VISTA 

Abbiamo già detto che se il metodo execute va a 
buon fine, viene richiamato con un forward il file 
ShowListaProdottijsp. Si tratta della pagina dove 
compare la lista dei prodotti disponibili per l'acqui- 
sto e dove l'utente può scegliere i prodotti da ag- 
giungere nel suo carrello. La sua implementazione 
riporta alcuni tag (facenti parte della grande fami- 
glia Struts HTML tag) interessanti, me vediamoli da 
vicino: 

<html:form action = "acquista" method = "post"> 

html:form, è il degno sostituto del HTML <form>. 
Tra i sui diversi attributi, uno dei più importanti è 
sicuramente: action. Questo consente di definire 
quale action richiamare nel metodo submitO del 
form. 

String acquistaProdottoval = "value(acquistaProdotto-" 

+ codiceProdotto + ")"; 

<html:checkbox property= 

"<%=acquistaProdottoval%>" /> 

html:checkbox, anche lui sostituisce HTML <input> 
checkbox, l'attributo property rappresenta il nome 
dell'attributo passato al momento della request 
In questo caso, è definito come la concatenazione di 
più stringhe questo perché Struts consente di defini- 
re nel FormAction una generica HashMap contenen- 
te diversi valori contrassegnati da un key da noi defi- 
nita, nel nostro caso la key è rappresentata dal codi- 



Lista Prodotti 



Codice 
Prodotto 


Descrizione 
Prodotto 


Prezzo 
Prodotto 


Prodotto 
Disponibile 


Acquista 
Prodotto 


001 


Fotocamera 


450 


V V 


r 


002 


Lettore DVD 


500 


m 


r 


003 


Televisore 


1000 


m 


r 


004 


PC 


450 


m 


r 


005 


Web-Cam 


100 


m 


r 


006 


Scanner 


100 


iÉ 


r 


007 


Tastiera PC 


50 


:; 


r 


009 


Tostapane 


35 


:: 


r 


0010 


SONYPS2 


199 


m 


r 



Aggiungi al Carrello 



ceProdotto. I valori memorizzati nelle HashMap, 
posso essere prelevati, mediante questa key. 
HHashMap è molto utile quando si devono passare 
liste di valori ma naturalmente, l'attributo property 
può anche essere semplicemente una Stringa, un int 
ecc.. 

<html:submit styleClass="invia" property="Submit"> 

Acquista </html:submit> 

htmhsubmit, sostituisce HTML <input> submit e 
rispetto ad esso, non presenta particolari differenze. 
Il suo look and feel della pagina ShowListaProdotti 
.jsp visibile in: Figura 3. 

Scelti i prodotti d'acquistare, l'utente prosegue la 
sua navigazione fino ad arrivare all'operazione 
PAGA. La pagina ShowCarrello.jsp mostra il conte- 
nuto del carrello, visibile in Figura 4. 



Dati Carrello 



Codice Carrello: 
Data Creazione: 



1 
12/02/2004 



Dettaglio prodotti aggiunti nel Carrello 



Codice prodotto 


Descrizione prodotto 


Prezzo Prodotto 


001 


Fotocamera 


450 


003 


Televisore 


1000 


009 


-ipane 


35 



Totale Ordine: 1485 

Torna alla Lista | Inserisci dati per l'Acquisto 



Fig. 3: Pagina jsp che visualizza i prodotti 



Fig. 4: Pagina jsp che mostra il contenuto del carrello 

Le istruzioni: 

<bean:write name="showCarrelloForm" property= 

"idCarrello"/> 

<logic:iterate name="showCarrelloForm" property= 

"listaProdotti" id="singoloProdotto"> 

Appartengono entrambi alla famiglia Struts Logic 
Tags. In particolare, beamwrite, consente di scrivete 
all'interno di una pagina jsp, il valore dell'attributo 
specificato nel property, prelevandolo dal FormAc- 
tion specificato nel name. Il Tag logic:iterate, con- 
sente invece di iterare un' attributo di tipo collec- 
tion. Ad esempio, combinato al tag beamwrite, con- 
sente di stampare in una pagina jsp, tutti i valori di 
una lista. (Questa operazione, è visibile tra i sorgen- 
ti della pagina in questione). 
La pagina InserisciDatiAcquisto.jsp è usata per l'in- 
serimento dei dati d'acquisto, visibile in Figura 5. 

< html : html >< html : html > 

<html:text property = "nome" ></html:text> 

<html:select property="tipoCarta"> 



► 30 /Aprile 2005 



http://www.ioprogrammo.it 



Un sito conforme al pattern MVC ■ T IOPROGRAMMO WEB 



Inserisci i dati per terminare L'Acquisto 



Dati Anagrafici: 

Nome o Ragione Sociale 

Cognome 

Indirizzo 

Codice Fiscale 

Telefono 

E-mail 

Dati Carta di Credito: 

Tipo Carta 
Intestatario Carta 
Numero Carta 
Scadenza 







(9 




|Catalda 




(!3 


|Via Teodosio 




n 


1 






|333/745826 




ià 


1 












| American Express J 




|Mary Catalda 




C9 


|4585 1258 4589 




n 


1 05 _J|2007 


zl(* 


) 








Torna alla Lista 


Acquista | 



Fig. 5: Pagina jsp per l'inserimento dei dati d'ac- 
quisto 



<html:option value="visa">Visa</html:option> 

<html:select> 

<html:button styleClass="invia" property="Submit" 

onclick="showl_istaProdotti();"> 
Torna alla Lista</html:button> 

Anche questi tags, fanno parte dei tag HTML Struts, 
e non fanno altro che ridefinire i loro omonimi in 
HTML. 



CONCLUSIONI 

Dagli esempi riportati nell'articolo, ma soprattutto 
tra i sorgenti dell'applicazione, avete scoperto, ma 
soprattutto scoprirete (almeno spero), tanti aspetti 
interessanti del framework Struts. Le sue potenzia- 
lità sono decisamente notevoli, degne di un nome 
così superbo!! Il mio carrello l'ho riempito. . . vi invi- 
to a riempire il vostro. Buona Spesa 

Valentina Muraglia 





SUL WEB 



http://jakarta.apache.org/ 
struts/userGuide 



AUTOMATIZZARE LO SVILUPPO CON ECLIPSE E LOMBOZ 



COMPILIAMO 



EEFffBflfflilFIM 



e Edit HTML Tidy Navigate 5earch | Project Run Window Help 
*ft I j™t ™t 

ackage Explorer Hierarchy ' 



ceBuild Ali 



Close Project 




: & J2src 

É-& model 
É-& StrutsWebAp 

È-& irnages 
; É-& WEB-INF 

| £3* classes 

I É-& lib 

! [^ build.properties 



u- e L ' .i •■ 



Q Apriamo eclipse e posizionia- 
moci sotto la root del progetto 
StrutsApp. Da questa posizione 
apriamo il menu a tendina Project e 
lanciamo il comando Build Project per 
iniziare il nostro lavoro. 



DEPLOY 




•.'.. •;-,;; '■ . ■■■■ 'A- » vr> 



Compare With 

■.■■.. 
HTML Tidy 



Add New EJB 

Stop Server 
Run Server 
Debug Server 



Ali 



Make default web urti 
Undeploy Hodule 



shin.a; ■ ;: ';,.-■-.. 



B Posizioniamoci sotto la dir Struts- 
WebApp, col il tasto destro del 
mouse selezioniamo la voce di menu 
Lomboz J2EE, si aprirà un nuovo menù, 
da questo selezioniamo il comando 
Deploy Module. 



ESITO DEPLOY 



: ; :■ ' : '.'. V(! :■■ : 



Properties Lomboz J2I 



<b ' ': .... . . ■ ' : ' ■ ; '"' 



[jar] 

[copy] 

[delete] 

[delete] 

deployTool : 

deploy: 



Building jar: C:\Valent:' 
Copying 1 file to C:\Valentina\Puo 
Deleting: C:\Valentina\Proguammi\J 
Deleting directory C:\Valentina\Pr 



Total time: 5 seconds 



H Dalla finestra Console di eclipse 
verifichiamo l'esito del deploy. 
Accertiamoci che alla fine compaia: 
BUILD SUCCESSFULU Questo ci 
garantisce che l'applicazione è stata 
correttamente inviata a Tomcat. 



VERIFICHIAMO IL DEPLOY SU TOMCAT 



LANCIAMO TOMCAT 




v I balancer 
□ jsp-examples 
_|ROOT 

lets-examples 
Q StrutsWebApp 



CU tomcat-docs 
Qwebdav 

|Stn tsWebApp.war 



□ Posizioniamoci sotto la directory: 
... tomcat\webapps e verifichiamo 
che ci siano sia la dir: StrutsWebApp che 
il file StrutsWebApp.war. Se ci sono... il 
deploy è terminato! 




H Lanciamo Tomcat con il comando 
"localhost:8080". per default il 
localhost gira sulla porta 8080, 
selezioniamo il comando Tomcat 
Manager con password = tomcat. 



LANCIAMO L'APPLICAZIONE 




Appiìcations 


Path 


Display Name 1 


/ 


Welcome to Tomcat 


/StrutsWebApp 

\ 


StrutsWebApp 



QA questo punto, comparirà la 
lista di tutte le applicazioni 
deployate su tomcat da qui 
selezioniamo StrutsWebApp e il 
gioco è fatto! 



http://www.ioprogrammo.it 



Aprile 2005/ 31 ► 



SISTEMA T 



Sfruttare al massimo Java 



Programmazione parallela con Java 



Thread 

e blocchi critici 

Per scrivere programmi "seri" è necessario conoscere un po' 

di programmazione parallela. La breve serie che inizia questo mese 

spiega come si usano i thread nei programmi Java 




Utilizza questo spazio per 
le tue annotazioni 



jn 




REQUISITI 



MdMMMMiUJlim 
.— Basi di Java, 
UJ) ereditarietà, 
polimorfismo 




\^M \^M E^3 



Tempo di realizzazione 



E capitato a tutti di usare programmi 
che non sono bravi a fare più cose con- 
temporaneamente. Schiacci un tasto 
che lancia una lunga operazione... e tutto si 
ferma. Magari vuoi interrompere l'operazio- 
ne, ma non si può più schiacciare niente fin- 
ché non è finita da sola. Alcuni programmi 
non aggiornano nemmeno lo schermo, quin- 
di basta spostare la finestra per ottenere un 
inquietante macchione bianco. 
E che dire dei sistemi client- server? Quasi 
sempre, un server deve servire più client con- 
temporaneamente. 

Se apro un'applicazione multiutente, non 
posso certo aspettare che tutti gli utenti con- 
nessi prima di me siano usciti dal sistema. 
Anche in questo caso, il programma non può 
fare le cose "in sequenza". Per fortuna i com- 
puter ci permettono di ottenere l'illusione del 
parallelismo. Nello stesso programma, più 
sequenze di istruzioni possono girare "in pa- 
rallelo", come se avessero ciascuna una CPU 
dedicata. Queste sequenze di istruzioni si 
chiamano thread. In realtà questo paralleli- 
smo è un'illusione: la maggior parte dei com- 
puter hanno una sola CPU. 
Quest'unica CPU esegue una sola sequenza 
di istruzioni in ogni dato istante, ma è molto 
brava ad alternare velocemente le sequenze. 
Dando a ciascun thread un pezzo del suo 
tempo (time sharing), il computer fa in modo 
che nessun thread si senta abbandonato, e 
che tutti i thread procedano apparentemente 
di pari passo. 

I thread sono delle bestiole capricciose, ma 
non se ne può fare a meno: in molte situazio- 
ni, un programma "single thread" non è ac- 
cettabile. 
Per fortuna Java supporta direttamente i 



thread, senza bisogno di librerie esterne. 
Quindi fare programmazione parallela in Java 
è più facile che nella gran parte degli altri lin- 
guaggi. 



LA CORSA 
DELLE LUMACHE 

Per introdurre i thread scriveremo un breve 
simulatore di corsa di lumache: 

public class Lumaca { 

private final String _nome; 

public Lumaca(String nome) { 

_nome = nome; 

} 

— #public void corriFinoAITraguardoQ { 

System.out.println(toString() + ": 1 metro"); 



System.out.println(toString() + " 



System.out.println(toString() + ": arrivata!") 



2 metri"); 



±_ 



public String toStringQ { 



return _nome; 



Il metodo 



corriFinoAlTraguardo ( 



stampa il 



progresso della lumaca, che su un computer 
moderno è molto più veloce di una lumaca 
reale: tre metri di distanza in meno di un mil- 
lisecondo. 

public class CorsaDiLumache { 

public static void main(String[] args) { 

Lumaca[] lumache = creaLumacheQ; 

gareggia(lumache); 



► 32 /Aprile 2005 



http://www.ioprogrammo.it 



Sfruttare al massimo Java ■ T COVER STORY 



private static void gareggia(l_umaca[] lumache) { 


for (int i = 0; i < lumache. length; i++) 


lumache[i]. corri FinoAITraguardo(); 


} 


private static Lumaca[] creal_umache() { 


return new Lumaca[] { 


new Lumaca("Speedy"), 


new Lumaca("Fulmine"), 


new Lumaca("Furia") 


}; 


} 


} 



CorsaDiLumache crea tre lumache con nomi 
appropriati e le fa gareggiare una dopo l'altra. 
Il risultato non è particolarmente interessan- 
te: 

Speedy: 1 metro 
Speedy: 2 metri 
Speedy: arrivata! 
Fulmine: 1 metro 
Fulmine: 2 metri 
Fulmine: arrivata! 
Furia: 1 metro 
Furia: 2 metri 
Furia: arrivata! 

Per rendere le cose più divertenti, le lumache 
dovrebbero correre insieme, "in parallelo". 
Per farlo, ci servono i thread. 
Se vogliamo far girare un pezzo di program- 
ma in parallelo con altri pezzi di programma, 
dobbiamo implementare l'interfaccia java 
.lang.Runnable. Questa interfaccia definisce 
il metodoE 9ST che deve contenere il codice 



parallelo. Aggiorniamo la nostra Lumaca per 
farla diventare un Runnable: 

public class Lumaca implements Runnable... 

-# public void run() { 

corriFinoAITraguardoO; 



} 



Ora dobbiamo lanciare questo Runnable in 
parallelo con il resto del codice. Per farlo 
dobbiamo creare un java.lang.Thread. Uno 
dei costruttori di Thread prende appunto un 
Runnable. Poi possiamo lanciare l'esecuzio- 
ne parallela con il metodo Thread .startQ: 



public class CorsaDiLumache... 


private static vo 


d gareggia(Lumaca[] lumache) { 


for (int i = 0; 


i < lumache. length; i++) { 


Thread t = 


new Thread(lumache[i]); 


t.start(); 


} 


} 



Thread. startO fa una serie di operazioni di 
basso livello che creano un nuovo thread nel- 
l'ambito dello stesso processo. A un certo 
punto, startQ chiamerà il metodo runQ del 
Runnable con cui è stato inizializzato il 
thread, e la Lumaca farà la sua breve corsa. A 
differenza di un normale metodo, Thread 
.startQ non aspetta che il metodo Runnable 
.runQ sia terminato, ma ritorna subito al pro- 
gramma principale. Quindi, mentre la Luma- 
ca parte, CorsaDiLumache crea altre due lu- 
mache e le fa partire nello stesso modo. 
Ecco il risultato: 

Fulmine: 1 metro 
Speedy: 1 metro 
Furia: 1 metro 
Fulmine: 2 metri 
Speedy: 2 metri 
Furia: 2 metri 
Fulmine: arrivata! 
Furia: arrivata! 
Speedy: arrivata! 

In generale, ogni volta che il programma gira, 
il risultato cambia. Il computer e la Java 
Virtual Machine garantiscono che i thread 
contenenti le lumache possono girare in 
parallelo, ma non fanno promesse per quan- 
to riguarda l'ordine e la frequenza con cui la 
CPU è allocata ai vari thread. Nel momento in 
cui usiamo i thread in un programma, il pro- 
gramma smette di essere deterministico e 
acquista una componente di casualità. La 
cosa è accentuata dal fatto che diverse Virtual 
Machine usano algoritmi diversi per gestire i 
thread, quindi un comportamento "comune" 



THREAD E PROCESSI 



Quando si parla di pa- 
rallelismo, spesso si fa 
confusione tra thread 
e processi. I thread e i 
processi hanno parec- 
chi punti in comune, 
ma sono cose molto 
diverse. Chiunque 
possegga un sistema 
operativo moderno 
usa regolarmente il 
parallelismo. Basta 
lanciare più program- 
mi, o lanciare più 
istanze dello stesso 
programma. Questi 
flussi di esecuzione si 
chiamano task o pro- 
cessi, e sono gestiti 



dal Sistema Operati- 
vo. Sono quelli che ap- 
paiono nel Task Mana- 
ger di Windows. I pro- 
cessi vivono come iso- 
le in aree di memoria 
diverse e controllate 
dal sistema, quindi un 
processo non può 
creare facilmente pro- 
blemi in un altro pro- 
cesso. Per lo stesso 
motivo, però, è diffici- 
le comunicare tra pro- 
cessi. Di solito si usa- 
no meccanismi "lenti" 
come la rete o i file. 
I thread sono flussi di 
esecuzione nell'ambi- 




TROPPA 
PRUDENZA 

Ricorda che 
synchronized fa 
l'esatto contrario di 
quello che un thread 
vorrebbe fare: dove il 
codice vorrebbe essere 
parallelo, synchronized 
lo rende nuovamente 
seriale. Questo 
significa che se 
sincronizzi troppo 
poco, ti esponi a bug 
molto pericolosi - ma 
se sincronizzi troppo, 
rischi che il tuo codice 
non sia affatto 
parallelo! Nelle 
prossime puntate di 
questo corso 
cercheremo una giusta 
via di mezzo per 
risolvere questo 
problema. 



to dello stesso proces- 
so (nel caso di Java, la 
stessa Virtual Machi- 
ne), e condividono lo 
stesso spazio di me- 
moria. 

Sono molto meno si- 
curi dei processi, per- 
ché due thread posso- 
no facilmente pestarsi 
i piedi a vicenda. 
In cambio, è molto fa- 
cile condividere le in- 
formazioni tra thread: 
in un programma Ja- 
va, i thread possono 
semplicemente 
condividere gli stessi 
oggetti 



http://www.ioprogrammo.it 



Aprile 2005/ 33 ► 



SISTEMA T 



Sfruttare al massimo Java 




su una JVM può diventare "raro" sull'altro. 
Una cosa interessante da notare è che il 
mainO termina presumibilmente prima della 
fine del programma. Dopo aver creato e lan- 
ciato i vari thread, Cor saDiLumache. mairi () 
ritorna al chiamante (la JVM). Ma il program- 
ma non termina finché non sono terminati i 
metodi run() di tutte e tre le Lumache. In ge- 
nerale e con alcune eccezioni, un programma 
non termina fin quando non è terminato l'ul- 
timo thread. Non possiamo dare quasi niente 
per scontato quando lavoriamo con i thread. 
Non è nemmeno detto che la Lumaca che par- 
te per prima sia anche la prima che stampa 
qualcosa sullo schermo. Nell'esempio reale 
trascritto qui sopra, la prima lumaca che arri- 
va al metro è Fulmine, anche se il thread di 
Speedy è stato lanciato per primo. Il program- 
ma ha fatto in tempo a creare e lanciare Ful- 
mine mentre il thread di Speedy non era an- 
cora arrivato alla prima stampa. Ma accade 
più spesso che sia Speedy ad arrivare per pri- 
ma, quindi questa privilegiata mette a buon 
frutto i suoi decimi di millisecondo di vantag- 
gio. Le operazioni di stampa sembrano alter- 



BLOCCARE I THREAD 



Con la parola chiave 
synchronized possia- 
mo dichiarare che un 
metodo è "atomico". 
Nessun thread può 
chiamare questo me- 
todo se un altro 
thread l'ha chiamato e 
ne deve ancora uscire. 

class LaMiaClasse { 
public synchronized 
void faiQualcosaQ { 
■■■} 

> 

Se creo un'istanza di 
LaMiaClasse e la con- 
divido tra più thread, 
ho comunque la ga- 
ranzia che solo un 
thread alla volta potrà 
invocare il metodo fai- 
QualcosaQ su quel- 
l'oggetto. Un metodo 
synchronized non è 
più "parallelo", ma 
"seriale". Se un 
thread chiama fai- 
QualcosaQ mentre un 
altro thread lo ese- 
gue, il secondo arriva- 
to resterà bloccato in 
attesa fino a quando 



la risorsa non sarà li- 
bera. Quando la risor- 
sa si libera, il thread 
viene sbloccato e può 
entrare nel metodo. 
Se più thread sono in 
attesa, la JVM assegna 
la risorsa a uno dei 
thread (non non 
necessariamente 
quello che aspetta da 
più tempo) in base al 
suo algoritmo 
preferito. 

La "sincronia" delle 
risorse si basa sul 
concetto di lock. Un 
metodo (o un altro 
blocco di codice) ha 
un "lucchetto" 
associato. Un thread 
chiude il lucchetto 
quando entra nel 
metodo, e lo apre 
quando ne esce. Se il 
lucchetto è chiuso, chi 
arriva aspetta fuori. 
La chiusura del 
lucchetto, l'esecuzione 
del codice e l'apertura 
del lucchetto sono 
un'unica operazione 
indivisibile. 
In Java tutti gli 



oggetti hanno un 
lock. Se chiamo un 
metodo synchronized 
su un oggetto (che è 
la mia risorsa 
condivisa), divento il 
temporaneo padrone 
del lock di quell'og- 
getto. Quindi altri 
thread possono 
tranquillamente 
chiamare lo stesso 
metodo su un altro 
oggetto della stessa 
classe, che ha un altro 
lock, ma non sullo 
stesso oggetto. 
Un'eccezione sono i 
metodi synchronized 
che sono anche static. 
In questo caso il lock 
non è quello 
dell'oggetto su cui 
viene chiamato il 
metodo, ma quello 
della sua classe (per 
essere precisi, quello 
dell'istanza di Class 
che la rappresenta). 
Quindi qualsiasi 
chiamata allo stesso 
metodo su qualsiasi 
oggetto della stessa 
classe è serializzata. 



narsi tra le tre lumache, ma anche questa è 
una questione di statistica. Mi è capitato ad 
esempio che una lumaca tirasse una volata 
fantastica: 

Fulmine: 1 metro 
Fulmine: 2 metri 
Fulmine: arrivata! 

CODICE PARALLELO 

(IN CINQUE SEMPLICI PASSI) 



public void X implements Runnable { 



Definisci una classe che implementa 
l'interfaccia Runnable 



public void X 


implements Runnable { 


public void 


run() { 




Utility. metodoStatico(); 


} 


} 



HIMel metodo run() scrivi il codice che 
deve essere eseguito in parallelo. Puoi 
pensare alla classe come ad un programma, 
dove il metodo run() sostituisce il mainQ. 



Thread t = new Thread(new X()); 



Istanzia un oggetto della classe, e usalo 
per istanziare un oggetto di classe 
Thread. 



t.startQ; 



Lancia il thread chiamando il metodo 
start(). 



public class Utility { 

public synchronized void metodoStaticoQ { 



} 



> 



Controlla che il codice parallelo non 
utilizzi risorse che possono essere 
condivise da altri thread, come metodi statici 
o reference ad oggetti che arrivano 
"dall'esterno". Se questo avviene, usa 
synchronized per proteggere le risorse 
condivise 



► 34 /Aprile 2005 



http://www.ioprogrammo.it 



Sfruttare al massimo Java 



T SISTEMA 



Speedy: 1 metro 
Speedy: 2 metri 
Furia: 1 metro 
Furia: 2 metri 
Speedy: arrivata! 
Furia: arrivata! 

Anche i "sorpassi" nel bel mezzo della corsa 
sono abbastanza rari - ma ogni tanto se ne 
vedono, come in questo caso: 

Speedy: 1 metro 
Furia: 1 metro 
Fulmine: 1 metro 
Speedy: 2 metri 
Fulmine: 2 metri 
Furia: 2 metri 
Speedy: arrivata! 
Fulmine: arrivata! 
Furia: arrivata! 

Vai, Fulmine! 

Leggere sullo schermo l'andamento della cor- 
sa è divertente, ma la cosa che ci interessa di 
più è il nome del vincitore. Con il tipo di out- 
put che abbiamo, non è molto comodo capire 
chi abbia vinto. 

Sarebbe meglio annunciare esplicitamente un 
vincitore ufficiale. Per farlo ho introdotto una 
classe Arbitro: 



System.out.println(toStnng() + ": arrivata!"); 
_arbitro.segnalaArrivo(this); 



> 



public class Arbitro { 


private boolean _garaChiusa 


= false; 


public void segnalaArrivo(Lu 


naca 1) { 


if(_garaChiusa) 


return; 


System. out.println("**** " 


+ 1 + " VINCE!!! ****"); 


_garaChiusa = true; 


} 


} 



Ora tutte le Lumache possono chiamare l'Ar- 
bitro quando arrivano al traguardo. La prima 
che lo fa viene annunciata come vincitrice. Le 
altre vengono ignorate, perché la gara è già 
chiusa. Dobbiamo modificare le Lumache in 
modo che conoscano e usino un Arbitro: 



public class Lumaca implements Runnable... 


private final Arbitro _arbitro; 


public Lumaca(String nome, Arbitro 


a){ 


_nome = nome; 


_arbitro = a; 


} 


public void corriFinoAITraguardo() { 


System. out.println(toString() + " 


: 1 metro"); 


System. out.println(toString() + " 


: 2 metri"); 



Se non vogliamo proteste e ricorsi, è impor- 
tante che le Lumache condividano tutte lo 
stesso arbitro: 

public class CorsaDiLumache... 

public static void main(String[] args) { 

Arbitro a = new Arbitro(); 

Lumaca[] lumache = creaLumache(a); 

gareggia(lumache); 

} 

private static Lumaca[] creaLumache(Arbitro a) { 
return new Lumaca[] { 
new Lumaca("Speedy", a), 



new Lumaca("Fulmine", a), 



new Lumaca("Furia", a) 



> 



La prima volta che ho fatto girare questo pro- 
gramma i risultati sono stati incoraggianti: 

Fulmine: 1 metro 
Speedy: 1 metro 
Furia: 1 metro 
Fulmine: 2 metri 
Speedy: 2 metri 
Fulmine: arrivata! 
Furia: 2 metri 
Speedy: arrivata! 
**** Fulmine VINCE!!! **** 
Furia: arrivata! 

Furia e Speedy hanno fatto in tempo a fare un 
po' di strada dopo che Fulmine aveva già ta- 
gliato il traguardo, ma prima che l'Arbitro la 
annunciasse come vincitrice ufficiale. 
Cose come queste sono normali nella pro- 
grammazione parallela, quindi non me ne 
preoccupo. Quello che invece mi preoccupa 
sono i risultati come questo: 

Speedy: 1 metro 

Furia: 1 metro 

Fulmine: 1 metro 

Speedy: 2 metri 

Fulmine: 2 metri 

Furia: 2 metri 

Speedy: arrivata! 

Fulmine: arrivata! 

***** Speedy VINCE!!! ***** 

***** Fulmine VINCE!!! ***** 

Furia: arrivata! 

Proprio così, abbiamo due vincitrici! E in mol- 




MAGIA MERA 

Inutile farsi illusioni: la 
programmazione 
parallela è difficile. Gli 
errori sono spesso 
subdoli, a volte perfidi. 
Capita che un bug si 
manifesti casualmente 
solo una volta ogni 
tanto (in questo caso si 
dice che il bug non è 
riproducibile), o che si 
manifesti mentre il 
programma gira ma 
non durante il 
debugging. A volte, le 
sequenze di 
avvenimenti che 
portano ad un errore 
sono talmente 
complicate da essere 
del tutto imprevedibili. 
Visto che non si può 
fare a meno dei thread, 
l'unica opzione che 
rimane è quella di 
imparare bene ad 
usarli, e di essere 
sempre molto prudenti 
quando si condividono 
risorse nel codice 
parallelo. 



http://www.ioprogrammo.it 



Aprile 2005/ 35 ► 



SISTEMA T 



Sfruttare al massimo Java 




ti esperimenti ne vengono fuori addirittura 
tre. Con tutta la simpatia per la salomonica 
decisione arbitrale, questo non è ciò che ci 
aspettavamo. Evidentemente il programma 
non funziona. Perché? 

Il colpevole è Arbitro. segnalaArrivoQ. Tutte e 
tre le Lumache chiamano questo metodo 
sullo stesso Arbitro. Ma ciascuna Lumaca vive 
in un thread separato, quindi capita che il 
metodo venga chiamato contemporaneamen- 
te da più thread. Si dice che l'Arbitro è una 
risorsa condivisa tra i thread. Le risorse condi- 
vise sono indispensabili se vogliamo che i 
thread interagiscano. Ma sono anche un pro- 
blema, perché nel momento in cui più thread 
accedono alla stessa risorsa, possono accade- 
re cose bizzarre. 

Quello che avviene in questo caso è che una 
Lumaca chiama per prima il metodo. Il meto- 
do controlla il valore di _garaChiusa, scopre 
che è false e prosegue con l'annuncio della 
vincitrice. In questo frangente, una seconda 
Lumaca chiama lo stesso metodo sullo stesso 
oggetto. Il flag _garaChiusa non è ancora 
diventato true, quindi anche questa seconda 
Lumaca viene dichiarata vincitrice. Poi en- 
trambe le esecuzioni del metodo settano 
_garaChiusa a true - due volte, ma ormai 
troppo tardi. Le due (o tre) esecuzioni del me- 
todo hanno già annunciato ciascuna una vin- 
citrice diversa. Che fare? 

Per evitare questo problema dobbiamo fare in 
modo che segnalaArrivoQ diventi un'opera- 
zione atomica. Questo significa che vogliamo 
che solo un thread alla volta possa eseguire il 



SENZA RUNNABLE 



Negli esempi abbiamo definito una 
classe che implementa Runnable, 
ne abbiamo creato un'istanza e 
l'abbiamo usata per costruire un 
Thread. 

Esiste un modo più veloce per 
definire un thread: ereditare 
direttamente dalla classe Thread: 

public class Lumaca extends Thread... 

Il resto della Lumaca è identico alla 
versione già esistente. Anche in 
questo caso si devono mettere le 
operazioni parallele in un metodo 
run() (nota che la classe Thread 
implementa a sua volta Runnable). 
Per lanciare il thread si deve 
chiamare starti), non run(). 
Quest'ultimo è un normale 
metodo, e non lancia alcun thread 



separato. Sarà starti) a fare il 
lavoro sporco e a chiamare a sua 
volta run(): 

public class CorsaDiLumache... 

private static void gareggia( 
Lumaca[] lumache) 

{ 

for (int i = 0; i < lumache. length; i++) 
lumache[i].start(); 

} 

In questo modo è un po' più 
semplice lanciare i thread. Ciò 
detto, di solito è meglio 
implementare Runnable che 
ereditare da Thread. 
Java non ha ereditarietà multipla, 
quindi una classe che eredita da 
Thread non può ereditare da 
nessun altro. 



metodo segnalaArrivoQ sullo stesso Arbitro. 
Per fare questo possiamo usare la parola chia- 
ve synchronized (vedi box). 

public class Arbitro... 

public synchronized void segnalaArrivo(l_umaca I)... 

A pensarci bene, questa non è la prima volta 
che le Lumache condividono una risorsa sin- 
cronizzata: era già successo nella versione 
precedente del programma, durante la stam- 
pa sullo schermo. Evidentemente il metodo 
System.out.printlnQ è sincronizzato. In caso 
contrario le Lumache potrebbero stampare 
contemporaneamente sullo schermo, crean- 
do il disastro che si può immaginare. Se cia- 
scun thread può terminare serenamente di 
stampare una frase e andare a capo prima che 
un altro thread cominci a fare lo stesso, lo 
dobbiamo a qualche tipo di sincronizzazione. 
A questo punto potremmo pensare di aver si- 
stemato tutto. Ma come spesso accade quan- 
do si usano i thread, il nostro programma ha 
ancora un subdolo bug. 

Ecco cosa è saltato fuori durante uno dei miei 
esperimenti: 

Fulmine: 1 metro 
Speedy: 1 metro 
Furia: 1 metro 
Fulmine: 2 metri 
Speedy: 2 metri 
Furia: 2 metri 
Fulmine: arrivata! 
Speedy: arrivata! 
***** Speedy VINCE!!! ***** 
Furia: arrivata! 

Potete immaginare la costernazione di Ful- 
mine, che si è vista soffiare ingiustamente la 
vittoria sotto il naso. Cosa diavolo è successo, 
questa volta? 

Il problema è che ciascuna Lumaca annuncia 
il proprio arrivo in due punti: prima lo stampa 
sullo schermo, poi lo segnala all'Arbitro. Ma 
tra le due operazioni può avvenire che un'al- 
tra Lumaca, in un altro thread, porti a termine 
entrambi gli annunci. Quindi la povera vinci- 
trice, che ha già annunciato per prima sullo 
schermo di essere arrivata al traguardo, si 
vede superare dalla concorrente che arriva 
prima al cospetto dell'Arbitro - che dà sempre 
retta alla prima Lumaca che vede. Questo do- 
vrebbe dare un idea di quanto la programma- 
zione parallela possa diventare subdola. 
Il mese venturo risolveremo anche questo 
problema. 

Paolo Perrotta 



► 36 /Aprile 2005 



http://www.ioprogrammo.it 



SISTEMA T ■ Windows Update Agent 



Aggiorniamo il sistema operativo e gli applicativi via codice 

Sistema sempre 
aggiornato 

Grazie a Windows Update Agent è davvero semplice usufruire dei 
servizi di aggiornamento offerti da Microsoft. In questo articolo 
parleremo delle tecniche per rilevare, scaricare ed installare patch 




Q CD Q WEB 



^ 



REQUISITI 



■jAI.WmMJ.li.MB 
Imi Basi di c# 



■B 



.Windows XP SP2 
(o altri OS aggiornati) 
.NET Framework SDK 



[^jjl^ì . 



Tempo di realizzazione 



Studiando le novità introdotte dal Platform 
SDK per Windows XP SP2 si scopre un'inte- 
ressante tecnologia: Windows Update Agent. 
Mediante le interfacce COM che costituiscono 
Windows Update Agent (WUA, d'ora in avanti) è 
possibile passare in rassegna tutte le patch presen- 
ti nel sistema ed eventualmente installare quelle 
mancanti. 







e aggiornamenti attualmente installati: 



S Werkkzeugl 

0|3 Windows Application Verifier 2. 50 

© Windows Media Player 10 

tf Aggiornamento rapido per Windows XP - KB834707 
," Aggiornamento rapido per Windows XP - KB885881 

- :: : ■■amento rapido per Windows \P - r : : : : : : 
!< Aggiornamento rapido per Windows XP - 'E 37333S 

-.:: : -; t--: =j :: -■= ::■:--• E ::: = :-' 
tf Aggiornamento rapido per Windows XP - -'E; :i :': 5 

-e; o--»~e-;o "»:'do per Windows XP -KB890175 




15/10/2001 
19/11/2004 
07/0172005 

o7/oyaoo5 

07/0172005 
07/01^2005 - 



Fig. 1: Installazione applicazioni mostra solo una 
parte delle informazioni relative ad un aggiornamento 

Nelle versioni future verrà introdotto il supporto 
per la scansione di una rete, gli amministratori 
potranno così sviluppare script ed applicazioni 
con avanzati schemi di distribuzione delle patch. 

Aggiornamenti automatici I 



È possibile imposte ::- - : : ■;.. :: - ; : ::■ :e ■; : sponibilità di importanti 
■;:: ornamenti e la loro installazione. Attivando Aggiornamenti automatici, è 
--"■-■- e :-e ve-c? ?:: --•"-■?:-:• so*: ??c kcc o"--?""s- :•?..::■"■■?:: -""-•? 
che vengano applicati altri aggiornamenti. 

Come funziona Aggiornamenti automatici 

* r -^.~. \L : .: : : . ..!....' : : ?"..U: : "-...'.1 : : ..'..Lr ■!:/ 

i-"""--j Scarica automaticamer: :e e ?:: :■"?■" e "i"i :o-s diati per il 
Win computer e installali: 



|Tutti i giorni _£] alle |3.00 _£] 



C Scarica ai ::•■•■:::•: -e - :e : ;:::-;-;-: -•? ascia decidere all'utente 

quando installarli. 
C Avvisa ma no- :•:■:" :■:" e -on installarli. 

C Disattiva gli aggiornamenti automatici. 

tll computer e p . . . -e "■?- e se -;■- '.erigono installati 
regolarmente gli aggiornamenti. 
Installa aggiornamenti dal sito Web di Windows Update . 



Fig. 2: Il Centro Sicurezza PC Windows è accessibile 
dal Pannello di Controllo 



Per il momento dobbiamo accontentarci dell'ana- 
lisi limitata al computer locale. Vedremo come rea- 
lizzare, con poche righe di codice, un programma 
simile ad Aggiornamenti automatici. 



NOZIONI DI BASE 

Lo spazio è tiranno, dunque non soffermeremo la 
nostra attenzione sulla gestione di server Windows 
Update Services (WUS) né tanto meno sulle discus- 
sioni riguardanti l'opportunità di affidarsi ad un si- 
stema automatico di aggiornamento. Rimbocchia- 
moci le maniche e controlliamo che il servizio "Ag- 
giornamenti automatici" (Figura 3) sia in esecu- 
zione o comunque awiabile in modo manuale: 
l'infrastruttura WUA poggia su tale componente. 



1 1 


>■"■• 


enti automatici 




|De 




| Tipo di avvio 


1 Connessone | 


ii>- - ..-:.- -- -_ --: 






::S-rl- Vr-C 




-- 








Manuale 


Sistema locale 


... 


«^Accesso secondario 






Ds« :;::: 


Sistema locale 




% Acquisizione di immagini di Window 


:'v;ia" 


Avviato 


Manuale 


Sistema locale 




t %Adobe LM Service 






IHuluUJM 


IUHB1III 








"aototo"" 


Sistema locale 




! %! - .-.- :■? : aie di sistema COM + 






Manuale 


Sistema locale 




%Ar*ivi rimovibili 








Sistema locale 




%Archiviazione proietta 




Avviato 


Automato) 


Sistema locale 




%ASP,NETAdmin Service 




Avviato 


-..-. ■■'*::; 


Sistema locale 




%A3P.NET State Service 












%Audio Windows 




Avviato 


-_::■"=: ::: 


Sistema locale 




^)-.~: _:zi: - = Eie e -::e. 












%Avvis 






::s-;: "-: 


Servizio locale 










Manuale 


Servizio di rete 




%Browser di computer 






-..:c^'.r: ::: 


Sistema locale 




%Centro sicurezza PC 






Disabilitato 


Sistema locale 




























%Cl ipB ook 






Disabilitato 


Sistema locale 



Fig. 3: Pannello di controllo -> Strumenti di ammini- 
strazione -> Servizi 



Il meccanismo viene messo in movimento dal mo- 
tore Windows Update AutoUpdate Engine conte- 
nuto nella libreria a collegamento dinamico \sy- 
stem32\wuaueng.dll. WUA risulta presente quan- 
do la versione di wuaueng.dll è 5.4.3790.1000 o 
superiore (Figura 4). Svilupperemo l'applicazione 
di esempio utilizzando le interfacce esposte dalla 
libreria \system32\wuapi.dll, nota anche come API 



► 38 /Aprile 2005 



http://www.ioprogrammo.it 



Windows Update Agent ■ T SISTEMA 



Proprietà - wuaueng.dll 



^JxJ 



Generale Veraione | Rrme digitali | Protezione | Riepilogo ] 



Veraione file: 



Descrizione: Windows Update AutoUpdate Engine 






Copyright: ® Microsoft Corporation. AJI rights reserved. 



Alile informazioni aulld veraione 
Nome elemento: Valore: 


Nome file originale 

Nome intemo 

Nome prodotto 

Società 

Veraione del prodotto 

Veraione file 




Lingua di sistema 









Applica 



Fig. 4: WUA è installato se la versione di wuaueng.dll 
è >= 5.4.3790.1000 

Client di Windows Update. Per nostra fortuna il 
.NET Framework nasconde le complessità della 
programmazione COM. Sarà sorprendentemente 
semplice esaminare la lista degli aggiornamenti 
disponibili e procedere alla loro installazione dopo 
la fase di download. Poiché WUA fa uso del servizio 
BITS (Background Intelligent Transfer Service) i tra- 
sferimenti avvengono in modalità asincrona. Nel 
caso in cui si perda la connessione nel mezzo di un 
trasferimento, il processo di download continuerà 
al collegamento successivo. Sul fronte della sicu- 
rezza c'è da notare che i dati scambiati sono pro- 
tetti dal protocollo SSL (Secure Socket Layer), inol- 
tre WUA installerà soltanto i pacchetti dotati di una 
firma digitale valida. 



IOAGGIORNO 

L'esempio proposto (Figura 5) è implementato 
in C# e richiede la presenza della libreria WUA- 
piLib .dll. Tale file può essere generato aggiun- 
gendo un riferimento a wuapi.dll in Visual 
Studio .NET, Delphi 2005 o Sharp Develop, in 
alternativa si può ricorrere allo strumento 
tlbimp.exe incluso nel .NET Framework SDK. La 
procedura da seguire per ricreare da zero il pro- 
getto è illustrata nel riquadro "Passi". Le inter- 
facce impiegate da IoAggiorno sono essenzial- 
mente quattro: 

• IUpdateSession - ogni operazione di ricer- 
ca, download, installazione, disinstallazio- 
ne, appartiene al contesto rappresentato da 
una sessione; 

• IUpdateSearcher - i metodi più importanti 



sono Search e QueryHistory. Il primo effet- 
tua una ricerca basata sui criteri specificati, 
il secondo restituisce tutte le informazioni 
relative agli aggiornamenti installati sulla 
macchina. 

IUpdateDownloader - dopo aver indicato 
una collezione di aggiornamenti da scarica- 
re si può passare al download. 

IUpdatelnstaller - questa interfaccia per- 
mette di installare/ disinstallare una colle- 
zione di aggiornamenti. Invocando il meto- 
do RunWizard si crea un assistente in grado 
di guidare l'utente durante l'installazione. 




Patch 



| Descrizione 



Ifr* 



PI Microsoft Windows Jour... Questo accessorio consente agli utenti che non dispongono di un co... O737240B 
PI : : Diornamento per Wind... Windows Media Connect rappresenta il modo più semplice per trasferi... 06753272 

" ,U.I,IJI.„IILIilJ,l,Ml..llJ.4l.y„.U.I,I.H.l.ll,L.ii!ir " 






Eventi 



Ricerca aggiornamenti in corso... 

Articoli Knowfedge Base {Pacchetto cumulativo di aggiornamenti per Outlook Express per Windows XP (KB337797)) 

http ://support .microsoft .com AJ3/337797 

Ho trovato 3 aggiornamenti! 

Articoli Knowfedge Base ^Pacchetto cumulativo di aggiornamenti per Outlook Express per Windows XF (KBB37797)) 



QZ 



Fig. 5: L'applicazione di esempio IoAggiorno 

Le interfacce di WUA prevedono due diverse 
modalità: sincrona e asincrona. La prima è 
immediata da gestire ma risulta bloccante, la 
seconda è più complessa però le operazioni 
sono svolte in background. La scelta di una 
modalità rispetto all'altra è delegata al pro- 
grammatore e dipende dalla tipologia di appli- 
cazione che si intende realizzare. IoAggiorno 
opera in modo sincrono e consente di: ricevere 
dal sito Windows Update la lista degli aggior- 
namenti disponibili, scaricare /installare in mo- 
do selettivo i pacchetti e visionare la sequenza 
degli aggiornamenti installati. Il programma, 
per aggiornare il sistema, richiede una connes- 
sione ad Internet precedentemente stabilita. 
La verifica dello stato di connessione è attuata 
dalla funzione InternetGetConnectedState 




I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



o 



System. Runtirne.InteropServices.COMException (0x30070422): Impossibile avviare il servizio. Il servizio è disabilitato oppure 
non è associato ad alcuna periferica attiva. 

at WUApiLib.UpdateSearcherClass.Search(String criteria) 

at IoAggiorno . UpdaterForm . RicercaAggiornamentiO 



Fig. 6: Se il servizio "Aggiornamenti automatici" è disattivato viene visualizzato 
questo messaggio 



http://www.ioprogrammo.it 



Aprile 2005/ 39 ► 



SISTEMA T 



Windows Update Agent 




esportata da wininet.dll. Se il servizio "Aggior- 
namenti automatici" è disabilitato viene mo- 
strato un messaggio di errore (Figura 6). 
Il criterio di ricerca adottato da IoAggiorno è 
stabilito dalla chiamata al metodo Search: 

Aggiornamenti = Ricerca. Search("lslnstalled=0 and 

Type='Software"'); 



? "SI" : "NO" 



} 



L'interfaccia IAutomaticUpdatesSettings è do- 
tata del metodo SaveQ, quindi, dopo aver mo- 
dificato con banali assegnazioni la configura- 
zione di "Aggiornamenti automatici", si può 
invocare: 



In breve vengono rilevati gli aggiornamenti 
della tipologia "Software" non ancora installa- 
ti (Islnstalled -0). Per cercare i driver più 
aggiornati basta sostituire Type -'Software' 
con Type- 'Driver'. La documentazione di WUA 
illustra una decina di criteri impiegabili nelle 
ricerche. 

Sul CD allegato alla rivista trovate il codice 
sorgente dettagliatamente commentato. 



AU.Settings.Save(); 

Ovviamente non ha senso indicare il giorno 
della settimana e Fora in cui aggiornare il si- 
stema se la proprietà NotificationLevel è im- 
postata ad un valore diverso da "Scheduled In- 
stallation". Per visualizzare la classica finestra 
di configurazione è sufficiente una sola istru- 
zione: 



AU.ShowSettingsDialog(); 




APPROFONDIMENTI 



Per verificare la pre- 
senza di WUA si può 
ricorrere a FileVersion- 
Info WuaVer = FileVer- 
sionlnfo.Get Version- 
lnfo(Environment.Syst 
emDìrectory+ "Wwuaue 
ng.dll");. I campi Pro- 
ductMajorPart, Pro- 
ductMinorPart, Pro- 
ductBuildPart e Pro- 
ductPrivatePart di 
WuaVer devono rap- 
presentare una versio- 
ne maggiore o uguale 
alla 5.4.3790.1000. La 
classe FileVersionlnfo 
appartiene allo spazio 
dei nomi System. Dia- 
gnostics. 



IMPOSTAZIONI 

Non abbiamo ancora visto come sia possibile 
accedere alle impostazioni di Windows Update 
Agent. Se vogliamo implementare un client 
WUA non possiamo prescindere da una simile 
caratteristica. Le impostazioni del servizio per- 
mettono di specificare il livello di notifica e la 
frequenza con cui ricercare gli aggiornamenti. 



fitmmtm 



friUMfr fctbkrilU^i^LL l 



mm&wm. 



oaù 



Ss *i I a 



E Varie 

ReadQnly 

Required 

Sched u led I rista I lation Day 
Sched u led I rista 1 1 ationTi me 



| Scheduled installation 
False 

False 

Every Saturday 
12 






NotificationLevel 

Indicates how elevateti users will be notified about Automatic Updates 
events. 



Servizio disponibile: NO 

Configura Aggiorna 

Impostazioni di schedulazione aggiornate! 



Fig. 7: PropertyGrid con le impostazioni di 
"Aggiornamenti Automatici" 



Il controllo PropertyGrid (Figura 7) è stato po- 
polato dal codice seguente: 

private void MostraConfigurazioneQ 

{ 

IAutomaticUpdates AU = new AutomaticUpdatesQ; 

IAutomaticUpdatesSettings Impostazioni = AL). Setti ngs; 



// Visualizza le proprietà nella griglia 

ProprietàWUA.SelectedObject = Impostazioni; 

// Mostra lo stato di WUA 

EtichettaStato.Text += (AU.ServiceEnabled == true) 



CREAZIONE DEL PROGETTO 



^^E23 



Tipi progetto: 



|ii£j 



-t3 Visuale* Projects 
E-Cl Visual C++ Project; 

■■■■C~ì Setup and Deployment Projects 
R+r~l Altri progetti 

■■■■C~ì Soluzioni di Visual Studio 



"1T¥ 

p # m 



A project fior creating an application Witti ; 






| IoAggiorno 



zi 



Percorso: I c:^lAL\IoProgrannmo 

Il progetto verrà creato in e: ^AL'JoP ::■?■■"•' : ':-;; : ": 



T Altro 



J 




D Assumendo che il vostro ambiente di 
sviluppo sia VS.NET è necessario creare 
un'applicazione Windows in C# 
(CTRL+SHIFT+N). Sharp Develop e Delphi 2005 
prevedono progetti analoghi. 

RIFERIMENTO A WUAPI 



| Projects | 



Nome componente | Versione lib... | Percorso \-*\ 


WMI ADSI EKtension Type Lib. . . 1.0 C:\WINDOWS^y5tem32tyvbe. . . 
WMICntJ 1.0 Type Library 1.0 C:\WINDOWSlSystem32Vbe... 
WMIScriptUtils 1.0 Type Library 1.0 Ci^rogrammi^ile comuniVIic, , , 
WMPDeskBand 1.0 Type Library 1.0 Ci^ROGRA^WINDOW^V .. 
WMPProxyLib 1.0 C:\WINDQWS^ystem32Vjro... 
WMSClientNetManager 1.0 Ty... 1.0 C: 1.WINDO WS V;ystem32Vvrn . . . 
WMTImportLib 1.0 C : programmi Vlovie Maker Vi... 
WPDSp 1,0 Type Library 1.0 C:\WINDOWS^ystem32\wpd... 
WSHControllerLibrary 1.0 C : \WINDO WS^ystentflVsh . . . 
WUAPI 2.0 Type Library 2.0 C:1,WINDOWSVystem32Vvua... 
wuaueng 1.0 Type Library 1.0 C:\WINDOWS^ystem32Vua... — 
X.THwpwpr I.OTvnelibrarv 1.0 n:\WTNnnWRlqvstpm37\X3n... Zi 



Componenti sele: :■" • : : 



| Origine 



E 



3. 



J. 



H L'utilizzo delle interfacce WUA richiede un 
riferimento alla type library WUAPI (menu 
Progetto->Aggiungi riferimento). Si noti la 
presenza della clausola using WU Api Lib; in 
Formf.cs. 



► 40 /Aprile 2005 



http://www.ioprogrammo.it 



Windows Update Agent ■ T SISTEMA 



Con poche righe di codice si ottiene la lista 
dettagliata degli aggiornamenti installati: 

UpdateSession Sessione = new UpdateSessionQ; 

UpdateSearcher Ricerca = 

Sessione.CreateUpdateSearcherQ; 

// IUpdateSearcher ha il metodo GetTotalHistoryCount 
IUpdateHistoryEntryCollection Patch Presenti = 

Ricerca.QueryHistory(0,Int32.MaxValue); 



if (PatchPresenti.Count > 0) 



{ 



// Mostra i dettagli (titolo, data, etc.) delle patch 

rilevate 



} 



Le informazioni riguardanti il sistema si ricavano 
ricorrendo all'interfaccia ISystemlnformation. 
A titolo di esempio, se si vuole determinare la ne- 
cessità di un riawio al fine di completare un'in- 
stallazione: 



ISystemlnformation info = new SystemInformation(); 
if (info.RebootRequired) MessageBox.Show( 

"È necessario riavviare."); 



CONCLUSIONI 

L'applicazione IoAggiorno sfrutta solo una 
parte delle funzioni di WUA: la documentazio- 
ne distribuita con il Platform SDK, reperibile 
anche tramite MSDN, descrive tutte le interfac- 
ce e le enumerazioni supportate. 
A titolo di esempio è possibile utilizzare l'inter- 
faccia IDownloadProgress per gestire una barra 
di progresso che mostri l'avanzamento delle 
operazioni di download. Lascio a voi il compito 
di esaminare i dettagli delle interfacce non de- 
scritte nell'articolo, vi garantisco che non man- 
cheranno le sorprese. Alla prossima! 

Salvatore Meschini 





APPROFONDIMENTI 



wus 

http://microsoft.com/wus 
Gli amministratori di 
rete possono utilizzare 
un server WUS per di- 
stribuire ai sistemi 
client, in maniera cen- 
tralizzata, gli aggiorna- 
menti prelevati dal sito 
Windows Update. 



MULTITHREADING 



PACCHETTI DA SCARICARE 



private void Lista3tn_Click (object sender, EventArgs e} 

•: 

Thread T = new Thread (new ThreadStart [RicercaAggiornanienti) ) ; 
// Avvia la ricerca di eventuali aggiornamenti (multithread) 

T. Start (} ; 
} 

// Scarica gli aggiornamenti selezionati 

private void ScaricaBtn_Click (object sender, EventArgs e} 

{ 

Thread T = new Thread (new ThreadStart ( S cari caAggi ornamenti) ) ; 

T. Start (} ; 
} 

// Connessione presente? 
private bool connesso () 

■: 

InternetConnectionState flags = 0; 
return InternetGetConnectedState [ref flags, 0) ; 
_1 



Si è preferito, per non scomodare i metodi asincroni, 
creare nuovi thread in modo da non perdere il controllo 

dell'applicazione durante le lunghe operazioni di: ricerca, 

download ed installazione. 



UpdateCollection DaScaricare = new UpdateCollectionQ; 
for (int i=0; i <= Aggiornamenti. Updates.Count-1; i++) 
{ 



// Gli aggiornamenti selezionati vengono aggiunti alla lista 



if (ListaBox.Items[i].Checked) 

J 

DaScaricare.Add(Aggiornamenti.Updates[i]); 



} 



} 



UpdateDownloader Scaricatore = Sessione.CreateUpdateDownloaderQ; 



Scaricatore. Updates = DaScaricare; // Cosa vogliamo scaricare? 
Scaricatore. DownloadQ; // Procedi! 



Dopo aver aggiunto alla collezione DaScaricare i 
pacchetti da trasferire, è sufficiente creare un'istanza di 

UpdateDownloader con CreateUpdateDownloaderQ e 

richiamare il metodo DownloadQ. 



RICERCA 



if (!connesso()) MessageBox.Show("Connessione a Internet non rilevata!"); 
else 



} 



Sessione = new UpdateSessionQ; 

UpdateSearcher Ricerca = Sessione.CreateUpdateSearcherQ; 
// Avvia la ricerca specificando un criterio: 



Aggiornamenti = Ricerca.Search("IsInstalled=Q and Type= 'Software'"); 
for (int i=0; i <= Aggiornamenti. Updates. Count-1; i++) 



ListaBox.Items.Add(Aggiornamenti.Updates[i].Title); // Nome della patch 
Lista Box.Items[i].SubItems.Add(Aggiornamenti.Updates[i].Description); 



} 



□ Nel metodo RicercaAggiornamenti viene creata una 
sessione di ricerca, le interfacce elencate nell'articolo 
sono dotate di una proprietà fondamentale: Updates. Sul CD 
trovate il codice commentato. 



INSTALLAZIONE 



UpdateCollection Dalnstallare = new UpdateCollectionQ; 



for (int i=0; i <= Aggiornamenti. Updates. Count-1; i++) 



{ if (ListaBox.Items[i].Checked) 

{ if (Aggiornamenti.Updates[i].IsDownloaded) 
{ 



DaInstallare.Add(Aggiornamenti.Updates[i]); 



> 



else 



Evento(Aggiornamenti.Updates[i].Title+" NON è stato 

scaricato." } 
Updatelnstaller Installatore = Sessione.CreateUpdatelnstallerQ; 



Installatore.Updates = Dalnstallare; 



IInstallationResult Esito = Installatore. Install(); 

// Avvia l'installazione 



HGIi aggiornamenti scaricati tramite Windows Update 
vengono installati con il metodo Installo di 
Updatelnstaller. In alternativa si potrebbe gestire questa fase 
con chiamate a Beginlnstall ed End Instali. 



http://www.ioprogrammo.it 



Aprile 2005/ 41 ► 



GRAFICA T 



Tecniche per la personalizzazione dei menu in .NET 



Scopriamo come cambiare l'aspetto dei nostri menu con VB.NET 

Oggi cambiamo 

■ 




Impariamo come strutturare al massimo il framework .NET per 
realizzare menu estremamente personalizzati e con grafica 
accattivante 




r 



CI CD □ WEB 



_menu.zip 




Utilizza questo spazio per 
le tue annotazioni 



r^ 




REQUISITI 



uj.wu.ujiu.Miim 

JJn Nozioni di base di 

OS? VB.Netedel.NET 

Framework 




Tempo di realizzazione 







Chi utilizza un ambiente RAD come Visual Stu- 
dio o simili, sarà ormai abituato a utilizzare 
questi strumenti in maniera visuale. Il meto- 
do più semplice per disegnare l'interfaccia di un'ap- 
plicazione è quello di prendere un elemento dalla 
casella degli strumenti e trascinarlo sulla form che 
rappresenta l'interfaccia. Utilizzando questi stru- 
menti di disegno visuale delle applicazioni mi viene 
spesso da pensare che essi coprono almeno l'80% 
delle necessità per la progettazione di un'interfaccia 
utente, peccato che a noi sviluppatori, prima o poi, 
serve anche l'altro 20%! Questa considerazione è 
quanto mai vera per i menu, principali o contestua- 
li, che sono un po' il "sale" delle nostre applicazioni. 
Un'interfaccia utente (UI per gli amici) ben realizza- 
ta contribuirà notevolmente alla facilità di utilizzo 
del vostro programma. Cosa c'è che non va nel buon 
vecchio menu che ci accompagna fin dalle prime 
edizioni del linguaggio Visual Basic? C'è che spesso 
risulta "drammaticamente" più spartano rispetto ai 
suoi "cugini" che gli utenti ritrovano nei programmi 
della suite di Office e simili. La prima differenza che 



Modifica Visualizza Inserisci Formato 5trumf 
fl Annulla digitazione 



Ripeti digitazione 



CTRL+Z 
CTRL+Y 



1 



jfc Tag[ia CTRL+X 

l^à Copia CTRL+C 

E§jj Appunti di Office... 
(3à In,= ° lla CTRL+V 

Incolla speciale... 
I Incolla come collegamento ipertestuale 



Cancella 
Seleziona tutto 



CTRL+5 (Tn) 



salta agli occhi è la presenza, nei menu di Word & 
Company, di piccole icone accanto al testo come 
quelle in Figura 1. Lo scopo di questo articolo sarà 
quello di vedere come fare ad implementare dei 
menu con elementi grafici personalizzati in .NET. 



IL PROGETTO 



|S MainMenul 



Fig. 2: Un oggetto MainMenu 
nell'area componenti dell'am- 
biente di sviluppo 



In Visual Studio, 
creiamo un Main- 
Menu su una form. 
L'aggiunta del me- 
nu, di per sé, non 
produce niente di 
visibile nella nostra 
form. L'unico risultato "apprezzabile" è quello di 
veder comparire, nell'area componenti dell'am- 
biente di sviluppo, l'icona che vediamo in Figura 2. 
Se clicchiamo su questa icona, si attiva in Visual Stu- 
dio l'Editor di menu che è poi quello che ci consen- 
te di aggiungere le varie voci, come possiamo vede- 
re in Figura 3. Le varie voci che vengono aggiunte at- 
traverso l'Editor di menu corrispondono ad altret- 
tanti oggetti del tipo System.Windows.Forms.Menu- 
Item che forniscono proprietà che consentono di 
configurare l'aspetto e la funzionalità della voce di 



BÌForm3 



HHE3I 



E 



~| | Digit 



are qui | 



Digitare qui 



Fig. 1: Tipico menu di Office 



Fig. 3: Editor di menu in Visual Studio 



► 42 /Aprile 2005 



http://www.ioprogrammo.it 



Tecniche per la personalizzazione dei menu in .NET ■ ▼ GRAFICA 



menu. Tra le proprietà ce n'è una che, visto il nostro 
obiettivo, ci interessa particolarmente: OwnerDmw 
.OwnerDraw è una proprietà di tipo Boolean, di de- 
fault impostata a false che indica se la voce di menu 
deve essere disegnata automaticamente dal sistema 
oppure se preferiamo farlo noi. Attratti dalla forza 
oscura della curiosità andremo ad impostare Ow- 
nerDraw su true, come in Figura 4, e proveremo a 
lanciare il programma con il consueto F5 e che suc- 
cede? Un disastro: al posto della voce di menu vedia- 
mo solamente un "rachitico" rettangolino. Beh... 
d'altra parte eravamo stati avvertiti: se la voce te la 
vuoi disegnare da te devi proprio disegnartela da so- 
lo, testo compreso! Bisogna rimboccarsi le maniche 
e scrivere qualche riga di codice utilizzando le classi 
grafiche di .NET. 









is mss^^^m m 


npm ir-iivii 






File | Digitare qui | 


Menultem2 5ystenn. Windows. ▼ 


-i^nBBHIH^Bn^ 


6[|9® H 


■ 1 Digitare qui 


::: 


E 


(DynamicPrope 




(Nanne) MenuItemZ 




Checked False 




Defaultltern False 




Enabled 


True 


. 




MdiList 


False 


MergeOrder 





MergeType 


Add 


ModiPiers Friend 




| True t| 




RadioCheck | 


▼ 


OwnerDraw 


False 




In 


dica se il diseqn 


:i dell'elemento 





Fig. 4: Impostazione della proprietà OwnerDraw 



PRENDIAMO LE MISURE 

Mettetevi nei panni del programma. Quando vi si 
chiede "disegnami la voce di questo menu" la prima 
cosa che risponderete quale sarà? "Quali sono le di- 
mensioni", naturalmente. Ed è proprio da qui che 
inizieremo. Ogni Menultem ha una serie di Eventi 
associati tra cui appunto py ffl] |^^jjj (misura l'og- 



getto) che serve appunto a conoscere la dimensione 
di una voce di menu prima di disegnarla. Lo schema 
del codice necessario a gestire l'evento è simile a 

• Private Sub Menultem l_MeasureItem(ByVal sender • 

As Object, ByVal e As System. Windows. Forms.- 

MeasureltemEventArgs) Handles 

Menultem l.Measureltem 

'aggiungere codice 



End Sub 

Tra i parametri notiamo: WHfìMà che è l'oggetto che 
ha originato l'evento (in questo caso il Menultem da 
disegnare) ed "e" che è un'istanza della classe Sy- 
stem. Windows.Forms.MeasureltemEventArgs che 
contiene il necessario per impostare la larghezza e 
l'altezza della voce di menu. Per impostare le di- 



mensioni della voce del menu utilizziamo il seguen- 
te codice: 

Private Sub MenuIteml_MeasureItem(ByVal sender As 
Object, ByVal e As System.Windows.Forms.Measure 
ItemEventArgs) Handles MenuIteml.Measureltem 



Dim myMenuItem As Menultem 
Dim altezza As Integer 



CType(sender, Menultem) 



Dim larghezza As Integer 



Dim misuraDelTesto As SizeF 



misuraDelTesto = e. Graphics. MeasureString( •■ 

myMenuItem. Text, Systemlnformation.MenuFont) 
altezza = Systemlnformation.MenuHeight 
larghezza = Systemlnformation.MenuCheckSize 

.Width + misuraDelTesto. Width 



e.ItemHeight = altezza 



e.ItemWidth = larghezza 



End Sub 



In pratica troviamo le dimensioni del testo della vo- 
ce del menu attraverso l'oggetto E Wlfflfà fornito da 



File 



System.Windows.Forms.MeasureltemEventArgs 
chiamando la funzione MeasureString ed impostia- 
mo larghezza ed altezza del menu attraverso Item- 
Width e ItemHeight, proprietà sempre contenute in 
System. Windows. Forms.MeasureltemEventArgs. Si 
noti come, in questa fase, ci siamo attenuti alle di- 
mensioni e font standard di sistema per i menu, re- 
cuperati attraverso la classe Systemlnformation. Pri- 
ma di personalizzare cerchiamo infatti almeno di ri- 
produrre il comportamento di una normale voce di 
menu. Se lanciamo nuo- 
vamente la nostra appli- 
cazione vedremo adesso 
al posto della voce di 

menu un rettangolo vuo- 
Fig. 5: la voce di menu 

prende forma con t0 > Fi g ura 5 - Ma tuttavia 

Measureltem manca ancora il testo. 



DISEGNAMI» 

Torniamo nei panni del programma, dopo che gli 
sono state comunicate le dimensioni dell'area da di- 
segnare di cosa avrà bisogno? Ovviamente di sapere 
cosa disegnare! È per questo che dobbiamo gestire 
un altro Evento: HiHBBSI Iil (Disegna l'oggetto! con 



un metodo dal seguente schema: 



'•Private Sub MenuIteml_DrawItem(ByVal senden 



As Object, ByVal e As System. Windows. Forms 

.DrawItemEventArgs) Handles MenuIteml.DrawItem 

'aggiungere codice 



End Sub 



Anche qui nei parametri ritroviamo il buon vecchio 
~[(che è il nostro Menultem) ed "e" che questa 





.NET 

E LE CLASSI 

GRAFICHE 

In .NET viene utilizzata 
un'implementazione 
avanzata dell'interfaccia 
di progettazione grafica 
(GDI) di Windows, 
denominata GDI+, che 
consente di creare 
grafica e testo, nonché 
modificare oggetti 
grafici come se fossero 
oggetti. GDI+ può essere 
utilizzato per eseguire il 
rendering di immagini 
grafiche in Windows 
Form e controlli. 
L'accesso alle classi 
grafiche avviene 
solitamente attraverso 
gli oggetti contenuti nel 
namespace 
System.Drawing. 



E LINGUAGGI 

Negli esempi riportati 
nell'articolo e nel CD è 
stato utilizzato Visual 
Basic .NET ma le 
tecniche illustrate sono 
valide anche per gli altri 
linguaggi del 
Framework come C#. 



IMAGELIST 

Il componente ImageList 
fornisce i metodi per la 
gestione di un insieme 
di oggetti Image è 
possibile aggiungervi 
immagini bitmap, icone 
o metafile a ImageList; 
gli altri controlli 
possono utilizzare le 
immagini attraverso un 
riferimento all'indice 
della proprietà Items. 



volta è un oggetto del tipo System.Windows.Forms- 



http://www.ioprogrammo.it 



Aprile 2005/ 43 ► 



GRAFICA T 



Tecniche per la personalizzazione dei menu in .NET 




.DrawItemEventArgs che ci metterà gentilmente a 
disposizione gli strumenti per disegnare. Pensiamo 
adesso alla struttura che dovrà avere la nostra voce 
di menu. Un rettangolo rappresenta l'intera area che 
contiene a sua volta due rettangoli: il più piccolo 
conterrà l'immagine, l'altro il testo. 



LE CLASSI 
PER I MENU 

L'oggetto menu 

corrisponde in .NET alle 

classi che discendono 

da System.Win- 

dows.Forms.Menu. 

Questa classe fornisce 

funzionalità comuni 

per tutte le classi di 

menu, in particolare 

System.Windows.Forms 

.MainMenu che 

rappresenta il menu 

principale 

dell'applicazione e 

System.Windows.Forms 

.ContextMenu che è il 

menu contestuale. 

Quello, per intenderci, 

che si attiva cliccando 

con il tasto destro su 

un controllo. 

MainMenu e 

ContextMenu sono 

composti da oggetti 

Menultem. Questi 

possono contenere altri 

oggetti Menultem, che 

rappresentano le voci 

dei sottomenu. 





[Rettangolo che 

J contiene l'icona 

/ |_o_il radio check 














TESTO DEL MENU 




» 










Rettangolo che~L--^ 
contiene il testo [ 





Fig. 6: la voce di menu prende forma con 
Measureltem 



L'intera area la conosciamo attraverso la proprietà 
Bounds (struttura di tipo System. Drawing.Rectangle) 
del System .Windows.Forms.DrawItemEventArgs che 
ci passa l'evento, i passaggi da fare sono quindi: 

1. trovare i rettangoli dell'icona e del testo; 

El colorare con lo sfondo appropriato tutta la voce 
del menu; 

3. se abbiamo un'immagine disegnarla nel rettan- 
golo icona; 

il disegnare il testo nel rettangolo apposito. 

L'intero metodo che gestisce l'evento Drawltem si 
presenterà quindi pressappoco così: 

Private Sub MenuIteml_DrawItem(ByVal sender As 

Object, ByVal e As System.Windows.Forms 
.DrawItemEventArgs) Handles Menulteml. Drawltem 
Dim ColoreTesto As Color = SystemColors.MenuText 
Dim ColoreSfondo As Color = SystemColors.Menu 
Dim Rettangololmmagine As System. Drawing 
.Rectangle = New Rectangle(e. Bounds. X, e. Bounds. 
Y, Systemlnformation.SmallIconSize.Width, 
Systemlnformation.SmallIconSize.Height) 
Dim AltezzaCarattere As Single 

e. Graphics. MeasureString( 

sender. Text, Me.Font).Height 



SUL WEB 



Una buona risorsa per 

capire il 

funzionamento delle 

tecniche più avanzate è 

l'articolo "Owner- 

Drawing in .NET" 

pubblicato in MSDN 

Magazine al link: 

http://msdn.microsoft.com 

/msdnmag/issues/04/02/Cut 

tingEdge/default.aspx 



AltezzaCarattere 



Dim margineVerticale As Single 



e. Bounds. Height - 
AltezzaCarattere 



Dim Retta ngoloTesto = New RectangleF(e. Bounds. X 

+ Rettangololmmagine. Width, e. Bounds. Y + 

(margineVerticale / 2), e. Bounds. Width - 

Rettangololmmagine. Width, e. Bounds. Height - 

margineVerticale) 

e. Graphics. FillRectangle(New SolidBrush( 

• ColoreSfondo), e.Bounds) 



e. Graphics. DrawString(sender. Text, Me. Font, New 

-• SolidBrush(ColoreTesto), Retta ngoloTesto) 



End Sub 



accanto al testo. Per semplicità, includiamo,nella fi- 
nestra di progettazione, un componente ImageList 
che non è altro che un contenitore di immagini e, 
agendo sulla proprietà Images della finestra proprie- 
tà, vi inseriamo una piccola immagine in formato 
GIF della dimensione di una piccola icona (16x16 
pixel). A questo punto, da codice, l'immagine potrà 
essere recuperata semplicemente con un riferimen- 
to all'indice: 

Dim Immagine As Image = ImmaginiMenu.Images(O) 

Oltre all'immagine dovremo però gestire anche lo 
"stato" della voce di menu, ovvero se il mouse vi è 
posizionato sopra o no. Per ottenere lo stato interro- 
ghiamo il risultato della congiunzione bit per bit del- 
la proprietà state di DrawItemEventArgs che è una 
combinazione dei membri dell'enumerazione del- 
l'oggetto DrawItemState: 

Dim selezionato As Boolean 

selezionato = (e. State And DrawItemState. Selected) = 
DrawItemState. Selected)) 

Il codice che gestisce Drawltem andrà quindi ag- 
giornato con il disegno dell'immagine e la gestione 
dello sfondo e del testo in base allo stato, seleziona- 
to o meno: 

Private Sub MenuItem2_DrawItem(ByVal sender As 

Object, ByVal e As System.Windows.Forms 
.DrawItemEventArgs) Handles Menultem2. Drawltem 
Dim ColoreTesto As Color = SystemColors.MenuText 
Dim ColoreSfondo As Color = SystemColors.Menu 
Dim Immagine As Image = ImmaginiMenu.Images(O) 
Dim selezionato As Boolean = ((e. State And 

DrawItemState.Selected) = DrawItemState.Selected) 



If selezionato Then 



ColoreTesto = SystemColors.HighlightText 

ColoreSfondo = SystemColors.Highlight 

End If 

Dim Rettangololmmagine As System. Drawing 
.Rectangle = New Rectangle(e. Bounds. X, e.Bounds. 
Y, Systemlnformation.SmallIconSize. Width, 
Systemlnformation.SmallIconSize. Height) 
Dim AltezzaCarattere As Single 



AltezzaCarattere 



e. Graphics. MeasureString( 

sender. Text, Me. Font). Height 



Dim margineVerticale As Single 



e. Bounds. Height - 
AltezzaCarattere 



Il metodo già consente di disegnare la voce di menu, 
ma noi vogliamo appunto aggiungere un immagine 



Dim Retta ngoloTesto = New RectangleF(e. Bounds. X 
+ Rettangololmmagine. Width, e. Bounds. Y + (margine 
Verticale / 2), e. Bounds. Width - Rettangolo 
Immagine. Width, e. Bounds. Height - margineVerticale) 
e. Graphics. FillRectangle(New SolidBrush( 

ColoreSfondo), e.Bounds) 

e. Graphics. Drawlmage(lmmagine, Rettangololmmagine) 
e. Graphics. DrawString(sender. Text, Me. Font, New 



^ 44 /Aprile 2005 



http://www.ioprogrammo.it 



Tecniche per la personalizzazione dei menu in .NET 



T GRAFICA 



SolidBrush(ColoreTesto), Retta ngoloTesto) 

End Sub 

Mandiamo in esecuzione il programma et voilà: il 

nostro duro lavoro sa- 



rà ricompensato da un 
menu con una voce 
decorata dalla piccola 
icona come quella che 
vediamo in Figura 7! 




Fig. 7: il risultato finale 



CONCLUSIONI 

Abbiamo visto la tecnica che è alla base del 
disegno personalizzato dei Menu. 
Tecnica che può anche essere utilizzata per la 
creazione di veri è propri componenti perso- 
nalizzati ereditando dall'interfaccia lExtender- 
Provider, componenti magari dotati delle fun- 
zionalità di design-time all'interno di Visual 
Studio. 

Francesco Smelzo 




uni menu coni icone ini sei mosse! 



DISEGNO DEL MENU 



File | Digitare qui 
Voce personalizzata 



Digitare qui 



Digitare qui 



Qln Visual Studio avviamo un progetto del ti- 
po Window Application e su una Form tra- 
sciniamo dalla casella degli strumenti un oggetto 
MainMenu provvedendo a disegnare le varie voci 
contenute. 

PROPRIETÀ OWNERDRAW 





■^^^WSe^H ^e^b 


Menultem2 System. Windows. Fornai 


m 


Ai 
2* 


m 


| 19 


Enable 
MdiList 


d 


True * | 




False 


MergeOrder 





MergeType Add 


Modifiers Friend 


BBBMW True _J 


RadioCheck False 


Shortcut None 



□ Selezionata la voce del menu (Menultem) a 
che vogliamo personalizzare, nella finestra 
proprietà impostiamo la voce OwnerDraw sul 
valore true. 

CONTROLLO IMAGELIST 




Aggiungiamo alla form un componente 
ImageList nel quale inserire le immagini 

in formato 16x16 pixel da mostrare accanto 

alle voci di menu. 



GESTIAMO L'EVENTO MEASUREITEM 



Private Sub MenuItem2_MeasureItem(ByVal sender As Object, ByVal e As 

MeasureltemEventArgs) Handles MenuItem2.MeasureItem 
Dim myMenuItem As Menultem = CType(sender, Menultem) 



Dim altezza As Integer 



Dim larghezza As Integer 



Dim misuraDelTesto As SizeF 



misuraDelTesto = e. Graphics. MeasureString(myMenuItem.Text, 

Systemlnformation.MenuFont) 
altezza = Systemlnformation.MenuHeight 



larghezza = Systemlnformation.MenuCheckSize.Width + misuraDelTesto.Width 



e.ItemHeight = altezza 



e.ItemWidth = larghezza 



End Sub 



□ Definiamo un gestore dell'evento Measureltem che imposta le dimen- 
sioni della voce di menu personalizzata. 

AREE DI DISEGNO, IMMAGINE E COLORI 



Private Sub MenuItem2_DrawItem(ByVal sender As Object, ByVal e As 

DrawItemEventArgs) Handles MenuItem2.DrawItem 

Dim ColoreTesto As Color = SystemColors.MenuText 

Dim ColoreSfondo As Color = SystemColors.Menu 
Dim Immagine As Image = ImmaginiMenu.Images(O) 

Dim Rettangololmmagine As System. Drawing.Rectangle=New Rectangle(e.Bounds.X, 
e.Bounds.Y, Systemlnformation.SmallIconSize. Width, Systemlnformation 

.SmallIconSize .Height) 

Dim AltezzaCarattere As Single 

AltezzaCarattere = e.Graphics.MeasureString(sender.Text, Me.Font).Height 
Dim margineVerticale As Single = e. Bounds. Height - AltezzaCarattere 
Dim RettangoloTesto = New RectangleF(e. Bounds. X + Rettangololmmagine. Width, 
e.Bounds.Y + (margineVerticale /2), e. Bounds. Width - Rettangololmmagine. Width, 

e. Bounds. Height - margineVerticale) 



(■■■) 



End Sub 



Definiamo un gestore dell'evento Drawltem impostando le aree dove 
verranno disegnati immagine e testo ed i relativi attributi prendendo 
l'immagine dall'ImageList in precedenza creata. 

DISEGNO DEGLI ELEMENTI 



Private Sub MenuItem2_DrawItem(ByVal sender As Object, ByVal e As 

DrawItemEventArgs) Handles Menultem2. Drawltem 

(■■■) 

e. Graphics. FillRectangle(New SolidBrush(ColoreSfondo), e. Bounds) 



e. Graphics. Drawlmage(lmmagine, Rettangololmmagine) 



e. Graphics. DrawString(sender.Text, Me. Font, New SolidBrush(ColoreTesto), 

RettangoloTesto) 



End Sub 



Sempre all'interno del gestore dell'evento Drawltem disegniamo lo 
sfondo, l'immagine ed il testo. 



http://www.ioprogrammo.it 



Aprile 2005/ 45 ► 



SCRIPTING T 



Estendere il software 



Potare i propri software di un linguaggio interno 

LUA: il linguaggio 
del software 

Aumentare la flessibilità del nostro software, aggiungendo un vero 
e proprio interprete di comandi testuali, potrebbe sembrare un 
lavoro molto oneroso. In realtà con LUA tutto è più semplice 




Utilizza questo spazio per 
le tue annotazioni 




Tempo di realizzazione 







Molti dei software più complessi in circola- 
zione non limitano l'interazione con l'u- 
tente alla sola interfaccia grafica. Chi 
lavora con programmi professionali, sa che è possi- 
bile estendere le varie funzionalità scrivendo un 
codice specifico per il software in questione. Questo 
codice, organizzato in "script", viene eseguito dal 
programma "ospite" e consente una vera e propria 
programmazione "ad alto livello". 



SCRIPTING CON LUA 

Uno script è su un semplice file di testo, né più né 
meno che il sorgente di un qualsiasi programma C o 
Java. Questo file può seguire due strade. Può essere 
elaborato così com'è da un programma detto inter- 
prete, oppure può essere trasformato in codice di 
basso livello, da un programma detto compilatore. 
Sia che si scelga la prima o la seconda strada, lo 
script passerà per una Virtual Machine (VM), che si 
occupa di fornire l'ambiente per l'esecuzione vera e 
propria. Esistono diversi linguaggi di scripting, noi 
descriveremo in particolare LUA che è un pacchetto 
disponibile gratuitamente al link www.lua.org. Qui 
si possono trovare anche i file di installazione, la 
documentazione ufficiale, le librerie, i sorgenti e un 
libro di apprendimento on-line. Non manca nulla 
insomma! 

Vedremo di seguito i fondamenti della sintassi di 
questo linguaggio. Chi è già avvezzo alla program- 
mazione non dovrebbe trovarsi spaesato, anche se 
sono presenti diverse peculiarità alle quali prestare 
attenzione. Probabilmente la cosa più semplice da 
fare è cominciare con un esempio, infatti eccolo: 

-- Il mio primo script con LUA 

x = 23 

y = "Ciao mondo!"; 



for z = 1, x do 



print (y, " — > ", z); 



end 



L'ESEMPIO 

Come è possibile intuire, l'effetto dello script prece- 
dente è quello di stampare a schermo per 23 volte la 
stringa "Ciao mondo!". Analizziamo riga per riga il 
codice. La prima riga è un commento e non influi- 
sce sulla funzionalità del codice ma solamente sulla 
sua leggibilità. Tutti i commenti in LUA sono su una 
singola riga e cominciano con " — ". Non esiste quin- 
di una sintassi particolare per i commenti su più 
righe, un po' scomodo ma. . . è così! 
Nelle successive due righe vengono assegnati valori 
alle variabili x e y. Come si può vedere LUA è un lin- 
guaggio "typeless", cioè non è previsto che si specifi- 
chi il tipo di ciascuna variabile (intero, stringa, ca- 
rattere ecc.), al contrario di quanto avviene in altri 
linguaggi. È l'interprete, o il compilatore, a gestire 
nel modo che ritiene più ragionevole, le varie situa- 
zioni. Se ad esempio scriviamo: 



print (a + b); 

verrà correttamente stampato il risultato della 
somma: 5. Col codice: 

e = "d vale: "; 

d = 10; 

print (e + d); 

l'interprete segnalerà il seguente errore : 

lua: prova.lua:3: attempi to perform arithmetic on 



► 46 /Aprile 2005 



http://www.ioprogrammo.it 



Estendere il software ■ T SCRIPTING 



global V (a string value) 

non si può infatti sommare una stringa a un intero, 
e non esiste una ragionevole conversione di tipi. 
Per la cronaca, se quello che si potrebbe intendere 
col simbolo "+" è il concetto di "concatenazione di 
stringa e intero", è possibile ottenere questo risulta- 
to usando la virgola "," come infatti avviene poche 
righe dopo. Sempre a proposito di punteggiatura, 
segnaliamo che la presenza del terminatore di istru- 
zione ";" è opzionale. Ogni riga potrebbe essere ter- 
minata semplicemente dal carattere di "a capo", tut- 
tavia LUA cercherà di interpretare come istruzioni 
multi-linea le righe che probabilmente presentano 
un errore o sono incomplete. Insomma, meglio met- 
tere il ";" che non metterlo: si evitano confusioni. 
Le ultime tre righe dell'esempio mostrano un sem- 
plice ciclo, realizzato col costrutto "for". L'istruzione 
tra il for e la clausola conclusiva "end" viene ripetu- 
ta assegnando alla variabile in oggetto (z) i valori 
dell'intervallo specificato (da 1 ax, cioè da 1 a 23). 
È da notare come il limite superiore (23) sia effetti- 
vamente un valore assegnato. Questo può generare 
un po' di confusione da chi viene da altri linguaggi, 
per cui è necessario prestare la dovuta attenzione 
per evitare errori difficili da scovare in fase di debug. 
Questa caratteristica fa il paio con un'altra peculia- 
rità di LUA: quando si dichiara un array di valori (in 
realtà una tabella, come vedremo) l'indice del primo 
elemento non è 0, bensì 1. 

LUA supporta altri due tipi di iterazione, che faran- 
no sentire a proprio agio i programmatori delle più 
varie estrazioni. È infatti possibile utilizzare sia il 
costrutto e Wnrmmche 



"repeat-untW 



I due cicli eseguono per 4 volte ciascuno (attenzio- 
ne!) una stampa a schermo, incrementando la 
variabile i. Da notare come il simbolo per il test di 
disuguaglianza (~=) sia leggermente differente da 
quello che si po' trovare in altri linguaggi. Le con- 
dizioni per ottenere il medesimo risultato nel 
while e nel repeat sono inoltre opposte tra loro, 
come ci si deve aspettare. Un'altra cosa degna di 
nota è la dichiarazione della variabile i con la clau- 
sola "locai". 

In LUA tutte le variabili hanno una visibilità globa- 
le una volta istanziate. Per ottenere un comporta- 



mento differente da questo, ad esempio se si vuole 
dichiarare una variabile localmente a una funzio- 
ne, si usa questa parola chiave. 



CONTROLLO DI FLUSSO 

Le condizioni logiche sono ovviamente usate anche 
dall'altra istruzione che si occupa del controllo del 
flusso del programma: il costrutto | 



if semplice 



if a < then 



a = 0; 



end 



clausola "else" 



if b == a then 



b = b+1; 



else 



b = b-1; 



end 



La sintassi è abbastanza intuitiva. Non è presente 
in LUA un costrutto simile allo "switch" del C/C++ 
ma si può ovviare a questa cosa utilizzando la 
clausola "elseif che consente di concatenare una 
serie di if in sequenza, omettendo la clausola di 
chiusura "end": 



locai i 


= i; 




while i 


~= 5 do 






print ("Ciclo 


while! --> ", i); 


i = i+1; 


end 


i = 1; 


repeat 


a 








print ("Ciclo repeat! — 


> ", i); 


i = i + 1; 


until i 


= = 5 





if a > 


then 








print ("a 


è positivo!' 


); 


elseif 


a < then 








print ("a 


è negativo 


"); 


else 




print ("a 


= = 0!"); 





niiL 

Sia i costrutti di ciclo che Yif prevedono un test su 
una condizione. L'esito di questo test può essere 
vero (true) o falso (false). L'unico concetto di falso 
che esiste in LUA è il nil. Nil è un valore "speciale", 
differente da qualsiasi altro valore assegnabile o 
tipo utilizzabile. Serve in LUA a rappresentare l'as- 
senza di un valore utile per una variabile. Ogni 
variabile non inizializzata assume il valore nil per 
default. È possibile inoltre assegnare a una variabi- 
le globale il valore nil per cancellarla. 
Facciamo un esempio, illustrando un altro concet- 
to, quello di multi- assegnazione. È possibile scrive- 
re in LUA una cosa del genere: 

x,y,z = l,2,3; 

Questa istruzione assegnerà, rispettivamente a x, y e 
z i valori 1, 2 e 3. È quindi perfettamente equivalen- 
te a: 




UTILIZZARE 
LUA SOTTO 
WINDOWS 

LUA si presenta come 
un pacchetto software 
molto snello, ottenibi- 
le scaricando dal sito 
ufficiale www.lua.org il 
file lua-5.0.2.tar.gz. LUA 
prevede sia un inter- 
prete interattivo che 
un compilatore. I nomi 
sono "lua.exe " e "luac 
.exe ". Non sono tutta- 
via presenti nel pac- 
chetto base in forma 
binaria. Per questo 
conviene scaricarli dal 
link http://lua-users.org/ 
wiki/LuaBinaries. Per uti- 
lizzare l'interprete è 
sufficiente aprire un 
prompt dei comandi e 
portarsi nella cartella 
contenente il file 
lua.exe ed eseguirlo. 
Un esempio di intera- 
zione è il seguente: 

> a = 23 [INVIO] 

> print (a) [INVIO] 



23 



Per eseguire lo script di 
esempio che si trova 
sul CD, è sufficiente 
digitare: 

lua lua_partel.lua 

Per compilare lo script 
di prova bisogna 
utilizzare luac.exe: 

luac -o lua_partel.out 

lua_partel.lua 



http://www.ioprogrammo.it 



Aprile 2005/ 47 ► 



SCRIPTING T 



Estendere il software 




print ("Ciao!"); 



end 



PERCHÉ 
ESISTE LUA 

Questo linguaggio è 

stato creato per 

rendere semplice la 

soluzione di problemi 

utilizzando poche righe 

di codice. I suoi punti 

di forza sono: 



• ESTENDIBILE: LUA è 

progettato per essere 

integrato con altri 

linguaggi come C/C++, 

Java, Fortran ecc. 

• SEMPLICITÀ: LUA è un 

linguaggio snello e 

semplice, facile da 

apprendere ma al 

tempo stesso molto 

potente. 

• EFFICIENZA: per le 

caratteristiche che 

offre, LUA presenta 

una implementazione 

alquanto efficiente. 

• PORTABILITÀ: LUA è 
disponibile per tantis- 
sime piattaforme, non 
solo Windows o 
Unix/Linux. 



Cosa succede se il numero degli elementi di destra e 
sinistra non corrisponde? Una cosa molto intuitiva. 
Nel caso di valori in soprannumero, come ad esem- 
pio: 

x,y= 1,2,3; 

il valore in eccesso (il 3) verrà semplicemente scar- 
tato, scomparendo senza lasciare traccia. Nel caso 
di variabili in eccesso invece, come: 

x,y,z- 1, 2; 

l'elemento non valorizzato sarà automaticamente 
posto a nil: 



a, b = "Ciao!"; 


if b then 


print( 


"Non verrò mai eseguita! :("); 


else 


print( 


"E' ovvio che tu sia qui!"); 


end 



FUNZIONI 

LUA prevede (ovviamente!) la possibilità di definire 
funzioni. Le funzioni possono essere utilizzate per 
eseguire un compito specifico (subroutine), oppure 
all'interno di espressioni per calcolare un valore. La 
lista degli argomenti va racchiusa tra parentesi 
tonde e, se non ci sono argomenti, va indicata la 
lista vuota: (). Esistono particolari casi in cui le pa- 
rentesi possono essere omesse, ma noi omettiamo 
di riportarli! Da una parte infatti è sempre opportu- 
no mantenere uno stile omogeneo di scrittura, dal- 
l'altra il lettore interessato avrà uno stimolo in più 
per leggere la documentazione ufficiale... 
Per quello che riguarda invece la definizione di una 
funzione la sintassi è abbastanza convenzionale: 

-- Utilizzo come calcolo di un valore 



function Seno (arg) 



-- funzione della libreria "math" 



return math.sin(arg); 



end 



-- Utilizzo come subroutine 



function Saluta(quantevolte) 



-- locai i = 1; 



if quantevolte > then 



for i = 1, quantevolte do 



print ("Ciao!"); 



end 



I parametri sono trattati esattamente come variabi- 
li locali e inizializzati col valore passato nella chia- 
mata. È possibile passare un numero di parametri 
diverso da quello indicato nella lista. Il comporta- 
mento di LUA sarà simile a quello già visto nel caso 
di multi- assegnazione. Nel caso di parametri in 
eccesso i valori superflui verranno scartati. Nel caso 
invece di parametri in meno, quelli senza inizializ- 
zazione verranno posti a nil. Questo comportamen- 
to potrebbe generare problemi se trascurato, tutta- 
via può rivelarsi utile qualora i parametri non pas- 
sati debbano assumere dei valori di default. Basta 
infatti fare un semplice test all'interno della funzio- 
ne sui valori che sono nil, per capire se hanno biso- 
gno di essere inizializzati o meno: 



function valore_default (a) 


if a : 


= = nil then 




pr 


int ("Non e' stato passato alcun valore!"); 


else 


pr 


int ("Il parametro vale: ' 


", a); 


end 


end 


valore. 


_default(); 




valore. 


_default(23); 





TABELLE 

Le tabelle non sono una struttura dati di LUA, ma la 
struttura dati per eccellenza. Tutti i tipi complessi 
vengono realizzati in LUA tramite tabelle, non da 
ultime le strutture dati che consentono di utilizzare 
il paradigma di programmazione "object oriented". 
Le tabelle di LUA sono degli "insieme associativi", 
cioè strutture dati che fanno corrispondere a un in- 
dice (o "chiave") un determinato valore. Le tabelle 
possono essere utilizzate alla stregua dei normali ar- 
rayC/C++: 



ArrayDilnteri = { 23, 46, 100}; 



end 



else 



ArrayDiStringhe = { "Ciao ", "Mondo!" }; 

È possibile accedere agli elementi di una tabella uti- 
lizzando le parentesi quadre []. L'unica accortezza 
da adoperare è, come già accennato, ricordarsi che 
l'indice di partenza non è ma 1: 

— Stampa "Ciao Mondo!" 

print (ArrayDiStringhe[l], ArrayDiStringhe[2]>; 

Nonostante l'inizializzazione di N elementi imposti 
un range di indici da 1 a N, è sempre possibile asse- 
gnare un valore a un qualsiasi indice al di fuori di 



► 48 /Aprile 2005 



http://www.ioprogrammo.it 



Estendere il software ■ T SCRIPTING 



questo intervallo: 



ArrayDiStringhe[23] = "Ciao Marte!"; 



print (ArrayDiStringhe[23]); 

Come è facile indovinare, provando ad accedere a 
una tabella con un indice non inizializzato, ci ritro- 
veremo a fare i conti col famigerato nil: 

print (ArrayDiStringhe[17]); 

stamperà: nil. Un aspetto fondamentale, che confe- 
risce notevole flessibilità a questa struttura dati, è il 
fatto che le tabelle possono essere eterogenee. In 
altre parole una tabella può contenere valori di 
diversi tipi: 

ArrayGenerico = {}; — Un modo di dichiarare una tabella 

ArrayGenerico[l] = 23; 

ArrayGenerico[2] = "Ri-ciao Mondo!"; 

Questo vuol dire che un elemento di una tabella 
può essere a sua volta una tabella: 

ArrayGenerico[3] = { 46, "Basta coi saluti, Mondo!"}; 
print (ArrayGenerico[3][2]); - Doppio indice per l'accesso 
— alla tabella interna 

È importante a questo punto sottolineare come gli 
elementi di una tabella siano tutti dei riferimenti ai 
valori originali e non delle copie degli stessi. Il se- 
guente codice: 

stringa = ArrayGenerico; 

stringa[3][2] = "Magia!"; 

print (ArrayGenerico[3][2]); 

stamperà: Magia! Nonostante non sia stata modifi- 
cata direttamente la tabella ArrayGenerico. In altre 
parole nelle tabelle vengono conservati i "puntato- 
ri" ai valori immessi e non i valori medesimi. Il con- 
cetto di "array associativo" è ancora di più accen- 
tuato dalla possibilità di considerare come indici 
delle vere e proprie "chiavi", rappresentate da strin- 
ghe. Analogamente a quanto avviene per le hash- 
table presenti in altri linguaggi, in LUA è possibile 
utilizzare le tabelle per memorizzare delle coppie 
"chiave-valore": 

TabellaChiavi["Nome"] = "Alfredo"; 

TabellaChiavi["Cognome"] = "Marroccelli"; 
TabellaChiavi["Eta"] = 26; 

Questo dovrebbe rendere evidente la possibilità di 
utilizzare le tabelle come strutture dati con campi 
personalizzabili. La cosa è ancor più vera se si con- 
sidera uno dei modi possibili di fare riferimento a 
questi valori, utilizzando la sintassi col punto ".": 



print ("Ciao! Sono ", TabellaChiavi.Nome, 

TabellaChiavi. Cognome, 
"\n e ho ", TabellaChiavi.Eta, " anni!"); 

L'utilizzo profondo delle enormi potenzialità offer- 
te da questa struttura dati è una cosa che richiede 
molta esperienza. Molti dei "trucchi" utilizzabili, in- 
fatti, sono difficili da cogliere per un neofita, ma 
conferiscono agli script in LUA un aspetto del tutto 
particolare! Consigliamo quindi molta pratica in 
questo campo, unita alla lettura di codice scritto da 
programmatori esperti, reperibile in quantità nella 
rete. 



CONCLUSIONI 

In questo articolo sono state trattate le basi della 
programmazione di script in LUA. Abbiamo visto 
come questo linguaggio abbia sia punti di contatto 
con i tradizionali linguaggi di programmazione, sia 
interessanti potenzialità aggiuntive. Come l'essere 
typeless o la straordinaria flessibilità delle tabelle, 
solo per citarne alcune. Il grosso delle potenzialità 
di LUA, tuttavia, risiede nella sua possibilità di "em- 
bedding" in un software "ospite". Sarà questo l'ar- 
gomento del prossimo articolo, non mancate! 

Alfredo Marroccelli 




UNA COMUNITÀ 
MONDIALE! 

I progetti che includono 
delle funzionalità imple- 
mentate con LUA sono 
davvero tantissimi. Per 
questo motivo la comu- 
nità di sviluppatori/uti- 
lizzatori in tutto il mon- 
do ha delle dimensioni 
non trascurabili. I link di 
riferimento dei "portali" 
su LUA sono http://lua- 
users.org/ e http://lua- 
forge.net/ . In particolare 
cliccando su http://lua- 
users.org/wiki/LuaAddons 
si ha accesso a una serie 
di tools e add-on 
impressionante. 





GETTIHIG STARTED 

STRINGHE 


SOTTOSTRINGHE 






Il seguente codice stampa una stringa 
— e la sua lunghezza 




s2 = "ioProgrammo con LUA!"; 

- Specifico stringa originale e estremi, 

partendo da 1 
s3 = string.sub(s2,6,12); 

— L'estrazione di una stringa non 

modifica l'originale 
print (s2); — > "ioProgrammo con LUA!" 
print (s3); — > "grammo" 




s = "Ciao!"; 

print (s); 

print (string.len(s)); 




Wm LUA prevede una serie di 
■■ librerie aggiuntive. 
Una parte delle funzioni fornite 
sono per la manipolazione di 
stringhe. 

MAIUSCOLE E MINUSCOLE 




E1 È molto semplice estrarre una 
KM parte di stringa da una più 
grande, specificando gli estremi. 
Come al solito l'originale non 
viene modificata. 

FORMATTAZIONE 






Modifico i caratteri della stringa 

precedente 
s_MAIUSC = string.upper(s); 
s_minusc = string.lower(s); 

- Stampa "CIAO!" e "ciao!" 

— Il carattere "!" non viene modificato 
print (s_MAIUSC); 

print (s_minusc); 




— Stampa di un numero con 2 cifre 

decimali 

n = 12.3456; 

print(string.format("n = %.2f", n)); — > 
"n = 12.35" (arrotonda...) 

— Stampa di una data con lunghezza 

fissa dei campi 

g = 17; m = 6; a = 2001; 

print(string.format("%02d/%02d/%04d", 
g, m, a)); --> "17/06/2001" 






El È possibile modificare le let- 
■■ tere maiuscole in minuscole e 
viceversa. La stringa modificata è 
fornita come risultato. 




WfM Si può formattare la stampa 
U di un numero analogamente 
a quanto avviene in C con la 
funzione printfQ. 





http://www.ioprogrammo.it 



Aprile 2005/ 49 ► 



DATABASE T I Microsoft Application Block 



Sfruttiamo il codice di Microsoft per Facilitarci la vita 

Meno codice 



per tutti! 



Vedremo come utilizzare le classi Data della libreria Application 
Blocks fornita da Microsoft per scrivere meno codice per accedere 
al database SQL Server 





I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 




Le classi che compongono il .NET Frame- 
work formano già un buon livello di 
astrazione del codice, permettendo di 
scrivere applicazioni con minor numero di ri- 
ghe di codice rispetto ad altre tecnologie. A 
volte, però, le classi del .NET Framework non 
sono ottimizzate e il programmatore deve 
scrivere sempre le stesse righe di codice per 
ottenere una determinata funzionalità. Per fa- 
re un esempio concreto prendiamo la funzio- 
nalità di richiesta dati ad un database, utiliz- 
zando un DataSet come contenitore. I passi 
sono sempre gli stessi: 

1. Creazione di un oggetto connessione tipo 
SqlConnection per specificare i parametri 
per collegarsi al database. 

2. Definizione di un comando SQL per ri- 
chiedere dati ad un database. 

3. Creazione di un oggetto DataAdapter che 
utilizzi la connessione e il comando SQL 
specificati precedentemente per ricavare i 
dati. 

4. Utilizzo del metodo FillQ del DataAdapter 
per inserire i dati ricavati dal database 
all'interno del DataSet. 

Questi passi si traducono nel seguente codice: 

SqlConnection conn = new 
SqlConnection("Server=.;Database=Northwind; 

Integrateci Security=true"); 

SqlDataAdapter da = new SqlDataAdapter("SELECT * 

FROM Products", conn); 

DataSet ds = new DataSetQ; 

da.Fill(ds); 

Nulla di trascendentale, vero, ma immaginia- 
mo che la nostra applicazione colloqui spesso 



con il database; il nostro codice sarebbe pieno 
di chiamate repetitive. Non sarebbe più sem- 
plice avere una situazione così? 

DataSet ds = SqlHelper.ExecuteDataset( 
ConnectionString, Data.CommandType.Text, "SELECT * 

FROM Products"); 

Daltronde la nostra richiesta era semplice; in 
base a questa stringa di connessione riempi- 
mi il DataSet con i record ricavati dal coman- 
do SQL che ti fornisco. Quello che esegue il 
metodo ExecuteDataset contenuto all'interno 
della classe SqlHelper fornita dai Microsoft 
Application Blocks è proprio quello che ci ser- 
viva. Niente codice ripetitivo, un'istruzione 
diretta e facilmente manutenibile. 



UTILIZZIAMO IL DATA 
APPLICATION BLOCK 

Anche se abbiamo già visto come un metodo 
del Data application block permette di otte- 
nere gli stessi risultati scrivendo meno codice, 
questa libreria fornisce altri metodi statici per 
effettuare altre operazioni interessanti come 
aggiornare i dati di una tabella tramite una 
transazione, ricavare dei dati utilizzando delle 
stored procedures, ecc. In questo articolo uti- 
lizzeremo il database NorthWind di MS SQL 
Server come supporto all'analisi del codice. 
Questa scelta è dovuta al fatto che il Quick 
Start Example che utilizzeremo per compren- 
dere il funzionamento dell'Application Block 
sfrutta proprio il database di Microsoft. Nono- 
stante questo l'Application Block supporta 
anche MSDE con le stesse modalità descritte 
in questo articolo. La differenza con i nostri 



► 48 /Aprile 2005 



http://www.ioprogrammo.it 



Microsoft Application Block ■ T DATABASE 



esempi risiede nel fatto che MSDE non sup- 
porta le stored procedure. 



L'AMBIENTE 

La prima operazione per utilizzare gli esempi 
forniti con l'installazione del Data Applica- 
tion Block è quella di eseguire uno script SQL 
all'interno del Query Analyzer in modo da ag- 
giungere tabelle e stored procedures sulle 
quali lavorare. Eseguiamo il tool scegliendo la 
voce Query Analyzer dal menu Microsoft Sql 
Server presente tra i programmi di Windows e 
inseriamo le giuste credenziali per collegarci 
al database. Copiamo il contenuto dello script 
CreateStoredProcedures.sql presente nel pro- 
getto di Visual Studio .NET all'interno del 
Query Analyzer ed eseguiamo i comandi. 
Il progetto Quick Start Example si trova nella 
directory di installazione dell'Application 
Block, è necessario aprirlo e compilarlo per 
avere un riferimento di quanto proposto nei 
paragrafi seguenti. 



j Connection String 


Retrieve Mul DataFleader 1 


'.":'. : : : " ' Ni ■ •'= .- . .'.''! ■■ tv' 


Retrieve Multi ,'ataSet 


Resulti 


Chai 

Fantàstica 
SasquatchAle 
Steeleye Stout 
Còte de Blaye 
Chartreuse verte 
Ipoh Coffee 

• :.' " - . 

Outback Lager 

■ Klosterbier 
Lakkalikobri 


Retrieve Single Row 


Look Up Single Itern 


Perforrn Transactional Update 


Retrieve XML Data 


Clear Resulti 





+ Environment.NewLine; 



} 



Tramite l'utilizzo del metodo statico Execute- 
Reader viene eseguita la stored procedure get- 
ProductsByCategory alla quale viene passato 
un parametro del valore 1 utilizzando la strin- 
ga di connessione specificata nella casella di 
testo della form principale. Tutto qui? Esatto, 
questo è tutto. Qualcuno potrebbe chiedersi 
chi si occupa di chiudere la connessione con il 
database dopo che il DataReader è stato uti- 
lizzato all'interno del ciclo while. La risposta 
la possiamo trovare all'interno del codice del 
Data application block: 

if (connectionOwnership = = 

SqlConnectionOwnership.External) 

{ 

dr = cmd.ExecuteReaderQ; 

} 

else 

{ 

dr = cmd.ExecuteReader( 

CommandBehavior.CloseConnection); 
} 

Qui il codice si chiede se la connessione è sta- 
ta aperta dall'esterno, ovvero il programmato- 
re si è preoccupato di gestire la connessione, 
oppure la gestisce il Data application block. 
Nel secondo caso il codice specifica di chiu- 
dere la connessione con il database alla chiu- 
sura del DataAdapter restituito dal metodo 
ExecuteReader. 




Il progetto è realizzato 
con la versione 2002 di 
Visual Studio .NET 
percui dovrete 
procedere alla con- 
versione della 
soluzione nel caso lo 
utilizziate con una 
versione successiva 
dell'ambiente di 
sviluppo. 



Fig. 1: II Quick Start Example in azione 



RICAVARE RECORD 
UTILIZZANDO 
IL DATAREADER 

Nel primo esempio viene utilizzato un SqlDa- 
taReader per scorrere tra i record ricavati dal- 
l'esecuzione di una stored procedure. 
Vediamo il codice utilizzato: 

private void cmdSamplel_Click(object sender, 
System .EventArgs e) 

{ 

SqlDataReader dr; 

dr = SqlHelper.ExecuteReader(txtConnectionString.Text, 

"getProductsByCategory", 1); 



txtResults.ClearQ; 



while (dr.ReadQ) 



_±_ 



RICAVARE RECORD 
UTILIZZANDO 
UHI DATASET 

Il codice contenuto all'interno del secondo 
pulsante permette di ricavare un DataSet 
riempito con i record ricavati dall'esecuzione 
della stored procedure getProductsByCategory: 

DataSet ds; 

ds = SqlHelper.ExecuteDataset(txtConnectionString.Text,fl 
CommandType.StoredProcedure, "getProducts 
ByCategory", new SqlParameter("@CategoryID", 1)); 



Il metodo statico 



ExecuteDataset 



accetta una 



txtResults.Text = txtResults.Text + dr.GetValue(l) 



stringa di connessione, un CommandType per 
specificare il tipo di commando fornito come 
terzo parametro e una lista di parametri, nel 
caso in cui il comando è una stored procedu- 
re. Il tutto è abbastanza semplice. 



http://www.ioprogrammo.it 



Aprile 2005/ 49 ► 



DATABASE T I Microsoft Application Block 




I MICROSOFT 

APPLICATION 

BLOCKS 

Nati come codice di 

supporto alla scrittura 

di applicazioni in C# e 

Visual Basic .NET i 

Microsoft Application 

Blocks sono degli 

assembly il cui codice è 

gratuitamente 

scaricabile dal sito 

http://download.micro- 

soft.com . Sono presenti 

diversi Application 

Blocks; uno per la 

gestione del database, 

uno per la gestione 

della cache, uno per la 

gestione delle 

eccezioni, ecc. Una 

volta completata 

l'installazione sul 

proprio sistema del 

Data Application Block 

sarà possibile accedere 

al sorgente della 

libreria dal menu Start 

di Windows che 

presenta il nuovo 

gruppo Microsoft 

Application Blocks. 

All'interno di esso 

sono presenti anche 

dei collegamenti alla 

documentazione e ad 

esempi realizzati in C# 

e Visual Basic .NET. 



RICAVARE UN SINGOLO 
VALORE 

Utilizzando la libreria ADO.NET è possibile 
ricavare un singolo valore come un aggregato 
(somma, valore massimo, ecc.) utilizzando la 
ExecuteScalar fornita dalla classe Command. 
Ma come al solito le operazioni da effettuare 
prima di chiamare questo metodo sono mol- 
te. Vediamo il codice dietro al pulsante Look 
up single item che utilizza una versione rivisi- 
tata del metodo ExecuteScalar: 

productName = (string)SqlHelper.ExecuteScalar( 

txtConnectionString.Text, CommandType. 
Stored Procedure, "getProductName", new 

SqlParameter("@ProductID", 1)); 

txtResults.Text = productName; 

Il metodo viene utilizzato per ricavare il nome 



di un prodotto il cui identificativo è uguale al 
valore specificato tramite il parametro @Pro- 
ductlD della stored procedure getProductNa- 
me. 



INSERIMENTO DATI 
CON SUPPORTO 
DELLA TRANSAZIONE 

Il metodo ExecuteNonQuery della classe Com- 
mand permette di eseguire un comando SQL 
che non ritorni nessun valore, solitamente un 
comando di inserimento o modifica dei re- 
cord di una tabella. Ad esempio, per utilizzare 
una stored procedure che inserisca dei dati è 
buona regola utilizzare una transazione in 
modo che se qualcosa non va per il verso giu- 
sto, questa possa essere utilizzata per riporta- 



CREARE QUERY IN MSDE/SQL SERVER 

In questo articolo abbiamo utilizzato come base 
per gli esempi Ms Sql Serve di Microsoft. Il quick 
start fornito con l'application block fa uso infat- 
ti del database di NorthWind distribuito con MS 
Sql Server. Nonostante questo è ovviamente 
possibile utilizzare in modo efficiente l'applica- 
tion block anche con altri sistemi meno costosi. 
Le analisi fatte nell'articolo rimangono tutte 
valide anche per altri sistemi, anche se il quick 
start potrà essere eseguito solo basandosi su MS 
SQL Server. In ogni caso allegato alla rivista 
trovate SQL Buddy un ottimo query editor che vi 
consente di connettervi ad altri database, primo 
fra tutti MSDE. Di seguito illustriamo una breve 
procedura per utilizzare SQL Buddy in 
alternativa al Query Analyzer che normalmente 
non é disponibile con MSDE. Se utilizzate SQL 
Buddy per eseguire l'esempio proposto in 
questo articolo, dovrete eseguire la query 
contenuta nel file SetupDataBase.sql contenuto 
nella directory di installazione di SQL Buddy. 



INSERIAMO 


IDATI 














M 








j W > i * j-J | O © I o o - 


1 


-d 










Database Explorer ,x 






















\3 3 




















WIB— EU 


1 






Name 1 Serve, 1 


1 locala locala 
DNewP,... 


|bcaM 




M.tataì 













^ISS 


£■*. 




E 




|,oca,r,o s , 






-d 










■ u " ii "■" i 


FU-Tn^C-, 


eo,ion 




| 


Ugnarne | 












Q Fi... IH 5... ÌD..| 


Ha SS ™d 1 














KJ 




| m a St e, 






JÉI 














^BJQ^H 






H 





CREIAMO UN NUOVO PROFILO 



HE necessario indicare un nome per il 
profilo, il nome della macchina che esegue 
MSDE o MS SQL e l'eventuale login e password 
per l'autenticazione 

ESEGUIAMO LA QUERY 




OSQL Buddy è in grado di gestire più di un 
database per volta. Ad ogni database 
deve essere associato un profilo contenente i 
dati per la connessione 



Le query possono essere editate 
direttamente dalla finestra principale di 

SQL Buddy e mandate in esecuzione tramite il 

pulsante nella barra dei menu 



► 50 /Aprile 2005 



http://www.ioprogrammo.it 



Microsoft Application Block ■ T DATABASE 



re la situazione dei dati nel momento esatto in 
cui la transazione è iniziata. Utilizzare una 
transazione in ADO.NET non è molto com- 
plesso ma richiede diversi accorgimenti che 
vengono facilitati dall'utilizzo della versione 
statica di ExecuteNonQuery fornita dalla li- 
breria Data Application Block. Vediamo il co- 
dice utilizzato nelF esempio per utilizzare una 
transazione: 

private void cmdSample5_Click(object sender, 
System .EventArgs e) 

{ 

using (SqlConnection conn = new 
SqlConnection(txtConnectionString.Text) ) 



_±_ 



conn.OpenQ; 



using (SqlTran saction trans = 

conn.BeginTransactionQ) 



_±_ 



SqlParameter paramFromAcc = new 

SqlParameter("@AccountNo", SqlDbType.Char, 
20); 



paramFromAcc. Value = "12345"; 



SqlParameter paramToAcc = new Sq I Para mete r( 
"@AccountNo", SqlDbType.Char, 20); 



paramToAcc.Value = "67890"; 



SqlParameter paramCreditAmount = new 

SqlParameter("@Amount", SqlDbType.Money ); 
paramCreditAmount.Value = 500; 



SqlParameter paramDebitAmount = new 

SqlParameter("@Amount", SqlDbType.Money ); 
paramDebitAmount. Value = 500; 



try 



jL 



SqlHelper.ExecuteNonQuery(trans, 

CommandType.StoredProcedure, "Debit", 
paramFromAcc, paramDebitAmount ); 
SqlHelper.ExecuteNonQuery(trans, 

CommandType.StoredProcedure, "Credit", 
paramToAcc, paramCreditAmount ); 



trans.CommitQ; 



txtResults.Text = "Transfer Completed"; 



±_ 



catch (Exception ex) 



_±_ 



trans.RollbackQ; 



txtResults.Text = "Transfer Error"; 



throw ex; 



finally 



{ conn.CloseQ; } } } 



Per comprendere meglio questo codice occor- 
re conoscere il prototipo del metodo statico 
ExecuteNonQuery fornito dalla libreria: 



public static int ExecuteNonQuery(SqlTransaction 

transaction, CommandType commandType, 

string commandText, params SqlParameter[] 

commandParameters) 

Il metodo accetta una transazione preceden- 
temente aperta ed associata ad una connes- 
sione, anch'essa aperta. Gli altri parametri 
sono gli stessi visti negli esempi precedenti 
con una particolare menzione per l'ultimo di 
tipo params. Grazie a questa parola chiave il 
metodo statico accetta un numero variabile di 
parametri che verranno automaticamente 
raggruppati ed inseriti all'interno di un array 
di tipo SqlParameter. 

È per questo motivo che il codice prepara una 
connessione, la apre e la associa ad un ogget- 
to SqlTransaction. Il metodo utilizza un riferi- 
mento ad una transazione già inizializzata e 
lascia che sia il programmatore a interessarsi 
della sua gestione. 



RICAVARE DATI 
IN FORMATO XML 

L'ultimo metodo fornito dalla libreria permet- 
te di ricavare un oggetto XmlReader conte- 
nente dati formattati utilizzando il formato 
XML. Questo grazie anche all'utilizzo della 
clausola FOR XML fornita da SQL Server che 
restituisce i record richiesti utilizzando una 
struttura XML. 

Vediamo il codice utilizzato all'interno del 
pulsante Retrieve XML Data dell'esempio: 

XmlReader xreader = SqlHelper.ExecuteXmlReader( 
conn, CommandType. Text, "SELECT * FROM Products 

FOR XML AUTO"); 

while (xreader.ReadQ) 

{ 

txtResults.Text = txtResults.Text + 

xreader. ReadOuterXml() + Environment.NewLine; 

} 

xreader.CloseQ; 

conn.Close(); 

il metodo statico ExecuteXmlReader restitui- 
sce un oggetto di tipo XmlReader riempito 
con l'XML restituito dalla query specificata 
come ultimo parametro. Successivamente il 
metodo Read viene utilizzato per scorrere tra i 
record ricavati che vengono stampati a video 
tramite la ReadOuterXml che legge il conte- 
nuto del nodo XML corrente, compresi i suoi 
markup. 

Fabio Claudio Ferracchiati 




http://www.ioprogrammo.it 



Aprile 2005/ 51 ► 



C#& MYSQL ■ T DATABASE 



Come sfruttare al massimo l'accesso concorrente ai database 

TVansazioni 
Con c# e MySql 

Le transazioni sono fondamentali per un uso corretto e sicuro delle 
basi di dati. In questo articolo capiremo cosa sono e a cosa servono e 
come sfruttarle in MySQL e in C# 



La definizione di transazione nella teoria delle 
basi di dati è piuttosto noiosa, e recita più o 
meno così: "una transazione è una sequenza 
di istruzioni correlate la cui esecuzione deve essere 
considerata un'unità indivisibile. Qualora una di tali 
istruzioni debba essere annullata, devono essere an- 
nullate tutte le istruzioni già eseguite nella stessa 
transazione". Nella pratica, è molto più interessante, 
e ora vediamo il perché. Immaginate di voler preno- 
tare un posto su di un volo e poi in un albergo, per le 
meritate vacanze dopo aver letto questo articolo. Il 
computer della vostra agenzia di viaggi dovrà con- 
trollare che ci sia posto nel volo e nell'albergo. Per 
esempio farà una query del tipo: 

1) select idposto from postiaereo where libero=true 

2) select idcamera from albergo where libero=true 

3) update albergo... 

4) update volo... 

se entrambi i risultati della 1) e 2) mostrano posti 
liberi potrà effettuare la prenotazione tramite le 
query di update. Poniamo che sull'aereo sia libero 
un solo posto. Ma che succede se intanto anche un 
altro lettore chiamiamolo "Bob" di questo articolo 
vuole andare in vacanza e mentre voi siete impegna- 
ti nella query 2) prenota l'ultimo posto sul volo? 
A questo punto la vostra agenzia farà l'update, ma 
non ci saranno posti liberi. Peggio ancora, farà co- 
munque l'update dell'albergo. Risultato netto, avre- 
te prenotato un posto in un albergo che non riusci- 
rete a raggiungere. Immaginate ora che Bob non ci 
sia, ma semplicemente che per qualche motivo l'up- 
date alla tabella volo generasse un errore. Il risultato 
sarebbe sempre lo stesso: una camera d'albergo de- 
solatamente vuota, ma prenotata... Se invece le que- 
ry 1-2-3-4 fossero eseguibili in modo tale che 

• finché non fossero finite nessuno potesse scrive- 



re su quelle tabelle 

• se ci fosse una condizione di errore o di anoma- 
lia si potesse tornare alla situazione di prima del- 
l'esecuzione 

i problemi non si sarebbero verificati. Infatti il posto 
sull'aereo non sarebbe stato occupato perché l'a- 
genzia do Bob non avrebbe potuto scrivere sulla ta- 
bella volo. Per eseguire le query in questo modo, ab- 
biamo bisogno di una transazione. In pseudo- codi- 
ce: start transaction; eseguiamo le nostre query. 
In caso di errore annulleremo tutti gli effetti delle 
query fin qui eseguite con il comando: rollback; al- 
trimenti renderemo durevoli le modifiche con il co- 
mando: commit. 

Abbiamo visto che le transazioni ci forniscono due 
aspetti fondamentali: 

• Rendono inaccessibili ad altri le tabelle che stia- 
mo modificando. Questo concetto, come vedre- 
mo più avanti, è più articolato: per esempio po- 
tremmo scegliere di far accedere in sola lettura, 
ma non in scrittura. 

• Ci permettono di annullare gli effetti dei coman- 
di già eseguiti nella transazione qualora lo desi- 
derassimo, per esempio in seguito ad una ecce- 
zione. 



Il\l MYSQL... IIUIUODB 

Questo articolo si propone di utilizzare le transazio- 
ni in MySQL attraverso l'uso di C#. Per prima cosa 
vediamo quale è il supporto alle transazioni in My- 
SQL. In questo DBMS ogni tabella che creiamo è ge- 
stita da un motore di memorizzazione, che ne defi- 
nisce il tipo. Il tipo più veloce, e quello di default per 
le versioni di MySQL precedenti alla 4.1 è il tipo my- 
ISAM. Purtroppo le tabelle mylSAM non supportano 





I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



jn 




REQUISITI 



■ imi i ' ^ 

ra basi di SQL, basi di C# 



Cx .NET framework 1.1 L 
OJ Visual Studio 2003, 
MySQL 



L^c^a^a. 



Tempo di realizzazione 



-y) ^ 



http://www.ioprogrammo.it 



Aprile 2005/ 57 ► 



DATABASE T ■ C# & MYSQL 




Q^M 



MA ACIDE 

Il modello di transazio- 
ni che viene più utiliz- 
zato, e che utilizzeremo 
con MySQL, è il model- 
lo ACID. ACID è l'acro- 
nimo di 

ATOMICITÀ: le transa- 
zioni sono atomiche e 
indivisibili: o le istru- 
zioni vengono eseguite 
tutte, o nessuna. 
CONSISTENZA: si passa 
da uno stato valido ad 
un altro stato valido 
ISOLAMENTO: le tran- 
sazioni non interferi- 
scono fra di loro. 
DURABILITÀ: quando 
una transazione è 
finita, i suoi effetti 
sono durevoli 

Le transazioni in My- 
SQL rispettano queste 
quattro proprietà. 



le transazioni. Invece il tipo InnoDB supporta tran- 
sazioni ACID. InnoDB è il tipo di default su MySQL 
4.1, ovvero ogni tabella creata sarà di tipo InnoDB se 
non altrimenti specificato. Se invece sviluppiamo 
DB per versioni precedenti di MySQL abbiamo due 
possibilità. La prima è quella di impostare il tipo del- 
la tabella al momento della sua creazione, sia trami- 
te i tool visuali ora molto comuni nello sviluppo 
MySQL, sia attraverso l'SQL: 

create table impiegato 

(IDImpiegato int not nuli auto_increment primary key, 
nome varchar(255), cognome varchar(255), 
salano int not nuli bonus int not nuli) type=InnoDB; 
specificando "type=InnoDB" 

l'altra possibilità è quella di inserire la voce 

default-storage-engine=INNODB 

nel file di configurazione del nostro MySQL (gene- 
ralmente my.inì). In questo modo ogni nuova ta- 
bella sarà di tipo InnoDB se non specificato altri- 
menti. Le tabelle InnoDB supportano quattro tipi 
di isolamento. Eccoli, ordinati dal più forte al più 
debole: 

• SERIALIZABLE - Il massimo per sicurezza e pu- 
lizia. Le letture e scritture avvengono in sequen- 
za anche in transazioni che vengono eseguite 
non in sequenza, visto che tutte le transazioni 
sono completamente isolate. È però il mecca- 
nismo più lento. 

• REPEATABLE READ (default) - Ogni transazio- 
ne agisce in una versione completamente isola- 
ta della tabella in cui ogni riga non cambia per 



r 


Lettura sporca 


Lettura non ripetibile 


Phantom rows 


SERIALIZABLE 


No 


No 


No 


REPEATABLE READ 


No 


No 


Sì (improbabile) 


READ COMMITTED 


No 


Sì 


Sì 


READ UNCOMMITTED 


Sì 


Sì 


Sì 


glabella h 1 vari tipi di tabella InnoDB A 



INSTALLARE MYSQL, I TOOL E IL MYSQL 
CONNECTOR.NET 



Per poter provare il co- 
dice illustrato in que- 
sto articolo, dovremo 
installare MySQL e un 
provider ADO.NET che 
ci permetta di accede- 
re ai dati. Potete tro- 
vare l'ultima versione 
di MySQL sul CD alle- 
gato alla rivista, oppu- 
re scaricarla online 
all'indirizzo 



http://dev.MySQL.com/ 
Allo stesso indirizzo, 
nella sezione down- 
loads, scaricare: 

• l'ultima versione del 
MySQL Query Browser, 
il versatile strumento 
di interrogazione di 
MySQL 

• l'ultima versione del 
MySQL Administrator, 
la console grafica di 



amministrazione delle 

istanze MySQL 

installate 

• l'ultima versione del 

MySQL Connector/NET, 

il provider ADO.NET 

fornito da MySQL. 

L'installazione dei pac- 
chetti è semplice, visto 
che tutti sono forniti 
di un installer guidato. 



tutta la transazione. Per questo la lettura è detta 
ripetibile. Improbabile, ma possibile, avere "ri- 
ghe fantasma": ovvero se si fa una query con una 
condizione due volte, ma fra le due letture un'al- 
tra transazione effettua delle scritture, per la se- 
conda lettura si potrebbero avere delle nuove ri- 
ghe, le righe fantasma. 

• READ COMMITTED - Le transazioni non sono 
più isolate, nel senso che le letture non sono ne- 
cessariamente ripetibili all'interno della stessa 
transazione. 

• READ UNCOMMITTED - In questo caso le tran- 
sazioni... non sono più transazioni, perché non 
sono più né isolate né consistenti. Abbiamo "let- 
ture sporche". 

per impostare il livello di isolamento, possiamo spe- 
cificare uno dei tipi nel comando 

set transaction isolation level 

ad esempio 

set transaction isolation level serializable; 

oppure modificare la chiave opportuna nel file di 
configurazione my.ini: 

[mysqld] 

transaction-isolation = {READ-UNCOMMITTED 

| READ-COMMITTED | REPEATABLE-READ 
| SERIALIZABLE} 

Nella Tabella 1 riassiumiamo le differenze tra i vari 
modelli rispetto alle possibili letture. Per ulteriori in- 
formazioni potete consultare il manuale online di 
MySQL all'indirizzo: http://deumysql.com/doc/mysql 
/en/innodb-tmnsaction-isolation .html 



TRANSAZIONI IN SQL 

Facciamo un esempio di creazione di transazione in 
SQL. Vogliamo dare un bonus di 1000 euro ad un 
nostro impiegato (con id-1) perché ha imparato ad 
usare le transazioni, prenderemo i 1000 euro dalla 
budget di gennaio della cassa aziendale. Dato che 
entrambe le operazioni debbono andare a buon fine 
per non rimetterci dei soldi di tasca nostra, potrem- 
mo utilizzare una transazione. Faremo riferimento 
alle tabelle create nella procedura a passi che corre- 
da l'articolo. Cominciamo la transazione 

start transaction; 

prendiamo i soldi dalla cassa 

update cassa set budget=budget-1000 where mese=l; 



► 58 /Aprile 2005 



http://www.ioprogrammo.it 



C#& MYSQL ■ T DATABASE 



tanto che ci siamo, insigniamo il bravo impiegato 
del titolo di impiegato del mese di gennaio 

insert into meriti (impiegatodelmese, mese) values(l,l); 

diamo i soldi al bravo impiegato. 

update impiegato set bonus= bonus+1000 where 

IDImpiegato=l; 

se tutto è andato bene, chiudiamo la transazione 

commit transaction; 

se invece la terza update non fosse andata a buon fi- 
ne, magari perché intanto l'impiegato 1 si è licenzia- 
to e ha aperto una sua società basata sulle transazio- 
ni, dovremmo annullare le prime due update. Per far 
questo faremo il rollback della transazione: rollback; 



e tutto tornerà come prima dell'inizio della transa- 
zione. 



TRANSAZIONI CON C# 

I nostri programmi però non sono scritti in SQL, ma 
in C#. Per poter accedere a MySQL da .NET dovremo 
utilizzare un providerADO.NET. Utilizzeremo il con- 
nector .NET fornito proprio da MySQL, che potete 
scaricare dagli indirizzi riportati nel box Sul Web. 
Utilizzeremo Microsoft Visual Studio 2003 per le no- 
stre prove, ma il codice scritto varrà chiaramente per 
qualunque ambiente .NET. Per prima cosa dobbia- 
mo creare un'applicazione WinForms C#, e aggiun- 
gere la Reference al MySQL Connector/NET. Nelle ulti- 
me versioni la dll MySql .Data.dll viene installato 
nella cartella C:\Programmi\MySQL\MySQL Con- 
nectorNet L0.4\bin\.NET LI o in una equivalente. 




CREAZIONE DI TABELLE CHE SUPPORTANO LE TRANSAZIONI 



APERTURA DEL QUERY BROWSER 



SETTIAMO L'INNODB 





MySQL Query Browser 1 .0. 7 beta [X| ! 
















Connection: | 
r=3y—* Username: | root 


I— Il I 

I 




Enter the password oh the user account 


Hostname: localhost 
Por*: |330G | 




Schema: | test 












Details» | OK 


Clear Cancel 













QDopo aver installato tutto il 
necessario siamo pronti per creare 
le nostre tabelle InnoDB. Per prima cosa 
dovremo far partire il MySQL Query 
Browser e fare il login. 

CREIAMO IL DATABASE 



create database ProvalnnoDB; 



BPer creare il nuovo schema di 
database su cui faremo le nostre 
prove, possiamo far partire il MySQL 
Administrator e creare un nuovo 
schema, oppure crealo direttamente nel 
MySQL Query Browser. Dopo avere 
inserito il comando nella finestra in alto 
premiamo poi il pulsante di esecuzione. 
Se non abbiamo avuto errori, il 
database sarà stato creato. Per 
accertarcene basta cliccare con il 
pulsante destro del mouse sopra la lista 
degli schemi che si trova a destra nella 
finestra del MySQL Query Browser e 
selezionare Refresh Schermata List. 



default-storage-engine=INNODB 



H Affinché la tabella che stiamo per 
creare supporti le transazioni deve 
essere del tipo InnoDB. Se abbiamo in- 
stallato una versione di MySQL uguale o 
superiore alla 4.1, questo avviene di de- 
fault per ogni tabella che andiamo a 
creare. Per replicare questo comporta- 
mento in versioni precedenti (per cui il 
tipo di default è MylSAM) dovremmo an- 
dare a modificare come segue una voce 
del file di configurazione (di solito sotto 
Windows tale file è my.ini e si trova nella 
directory di installazione di MySQL). 
Vedremo comunque nel prossimo passo 
come scegliere di volta in volta il tipo 
della tabella. 

CREIAMO LA TABELLA CON L'SQL 



use ProvalnnoDB; 



create table Impiegato 



( IDImpiegato int not nuli auto_increment 

primary key, Nome varchar(200), Salano 

int not nuli, Bonus int) type= InnoDB; 

insert into impiegato (Nome,Salario,Bonus) 

values ('Luca', 1000,100); 

insert into impiegato (Nome,Salan'o,Bonus) 
values ('Claudio', 1000,100); 



□ La pri,a riga definisce il database 
da usare. Vedremo che il nostro 
nuovo DB sarà selezionato nel pannello 
dei DB. Le altre righe creano la tabella. 
L'ultimo parametro, type= InnoDB;, spe- 
cifica il tipo. Questo comando non è 
necessario se si è certi che il tipo InnoDB 
è il tipo di default. Per vedere la tabella 
appena creata nella lista dei DB, sceglie- 
re Refresh Schermata List dal menu con- 
testuale. 



CREIAMO LA TABELLA CON 
L'INTERFACCIA A FINESTRE /1 



MySQL Tabi. Edito, 



Kàii S" ,-.=..■ 
















1 




: 






Indegni [|NDE^ 


~ 


Index Tjpe: [DEFAUL 


IH 







Hll MySQL Query Browser ci per- 
mette di creare tabelle in maniera 
molto semplice attraverso una interfac- 
cia a finestre. Basta fare click con il pul- 
sante destro sopra uno dei database nel 
pannello di destra e scegliere Create 
NewTable. In figura vediamo la creazio- 
ne di una tabella attraverso questo 
strumento. Lo stesso strumento può 
essere usato per modificare una tabella. 

CREIAMO LA TABELLA CON 
L'INTERFACCIA A FINESTRE /2 



* MySQL Table Editor 



«a*. 


£Tp£S -J^^—O^K*- 


ag eEn g ™ 


Jhrc-.locking.Reconnnnended 


aB eE„ BÌ „e 


KS5";" 


,a B e Engine 




eEnpne 




iEngta 


T,an S acti n:a te . , a ga eng. o called Bakelej DE 


.En*» 





Q Selezionando la linguetta TableOp- 
tions è poi possibile specificare 
che intendiamo creare una tabella 
InnoDB. 



http://www.ioprogrammo.it 



Aprile 2005/ 59 ► 



DATABASE T ■ C# & MYSQL 




Il Connector mette a disposizione dello sviluppatore 
la classe MySqlTransaction. Gli oggetti di tipo MySql- 
Transaction rappresentano una transazione, e pos- 
sono essere associati ai comandi che vogliamo in- 
cludere nella transazione. Dopo aver letto i paragra- 
fi precedenti, appaiono chiari gli scopi dei membri 
della classe Tabella 2. 

A questo punto possiamo procedere a scrivere il co- 
dice. Possiamo creare un Button sulla form appena 
creata, e inserire il codice nell'evento OnClickQ. Per 
prima cosa specifichiamo che intendiamo utilizzare 
il namespace adatto, scrivendo in testa al file: 



Transazione. Commit(); 



> 



Il Commandviene eseguito, e ritorna il numero di ri- 
ghe modificate. Se non c'è errore, alla fine facciamo 
il CommitO della transazione. Per rifarci all'esempio 
SQL sopra illustrato, potremmo sostituire la riga 

Transazione. CommitO; 

con la seguente, che controlla che l'impiegato da 
premiare sia ancora fra noi. . . 



using MySql.Data.MySqlClient; 



if (righeModificate= = l) 



Membro 


Tipo 


Scopo 


Connection 


Property 


Rappresenta l'oggetto MySqlConnection associato alla 
transazione 


IsolationLevel 


Property 


Rappresenta il livello di isolamento della transazione. 
Di tipo System.DataJsolationLevel 


Commit 


Method 


Esegue il commit della transazione, rendendo durevoli 
gli effetti dei comandi 


Rollback 


Method 


Esegue il rollback della transazione, annullandone gli effetti. 


^Tabella 2: 1 membri della classe MySQL Transaction ^ 




SUL WEB 



Si noti che per le versio- 
ni di MySQL precedenti 
alla 4.0 occorre abilitare 
il supporto InnoDB at- 
traverso l'impostazione 
manuale di opportune 
chiavi della sezione 
[MySQLd] del file di 
configurazione my.ini o 
my.cnf; è opportuno in 
tal caso fare riferimen- 
to al documento 
http://dev.MySQL.com/doc/ 
MySQL/en/innodb-in- 
MySQL-3-23.html 
della guida di MySQL. 



Ora creiamo la connessione (specificando l'oppor- 
tuna stringa di connessione, in cui inserirete i vostri 
dati): 

string ConnString="Database=ProvaInnoDB;Data Source= 
localhost;User Id = root; Password = marco "; 

MySqlConnection Connessione = new 
MySqlConnection(ConnString); 

Connessione. Open(); 

siamo pronti per creare il Command e la transazio- 
ne. Possiamo poi far partire la transazione e asse- 
gnarla al Command: 

MySqlCommand Cmd = Connessione. CreateCommand(); 
MySqlTransaction Transazione; 
Transazione = Connessione. BeginTransaction(); 
Cmd. Connection = Connessione; 



Cmd. Transaction = Transazione; 



mettiamo in un blocco try le operazioni sui dati: 



try 



{ int righeModificate=0; 



Cmd.CommandText •■ 



"update cassa set budget= 
budget-lQQO where mese=l" 



righeModificate= Cmd.ExecuteNonQuery(); 
Cmd.CommandText = "insert into meriti ( 

impiegatodelmese, mese) values(l,l);" 

righeModificate=Cmd.Executel\lonQuery(); 
Cmd.CommandText = "update impiegato set bonus= 
bonus+1000 where IDImpiegato=l;" 
righeModificate= Cmd.ExecuteNonQueryQ; 



{ Transazione. Commit();> 



else 



{ Transazione. RollbackQ; 



MessageBox.Show("Nessuna modifica effettuata"); 



> 



È opportuno notare che se si mettesse un break- 
point appena prima del CommitO, e si andasse con 
il Query Browser a fare la select sulle tabelle Impie- 
gato e Meriti, non si rileverebbero cambiamenti, vi- 
sto che la transazione non ha ancora effettuato le 
sue modifiche. L'altro caso in cui non vorremmo che 
la transazione scrivesse niente di durevole nel DB è 
quando ci fosse un errore. Se per esempio le prime 
due ExecuteNonQuery andassero a buon fine men- 
tre la terza sollevasse un'eccezione, avremmo perso 
1000 euro, spariti nel nulla! Occorre allora fare il 
RollBack nel blocco catch: 

catch(Exception exc) 

{try 

{ Transazione. Rollback();> 

catch (MySqlException ex) 

{ if (Transazione. Connection != nuli) 

{ MessageBox.Show(T eccezione durante il 
rollback! " + ex.GetTypeQ);} } 

MessageBox.Show("Nessuna modifica effettuata per 

l'eccezione: " + exc.GetTypeQ );} 

finally 

{Connessione. Close();> 

Dovremo controllare anche che non ci sia stata nes- 
suna eccezione durante il metodo RollBack(). 
Alla fine chiuderemo comunque la connessione. 



CONCLUSIONI 

Le transazioni sono indispensabili quando il proces- 
so da implementare coinvolge scritture e letture in 
tempi diversi e su diverse tabelle, ovvero nella mag- 
gior parte dei progetti che lo sviluppatore professio- 
nista si trova ad affrontare. Buona programmazione! 

Marco Poponi 



► 60 /Aprile 2005 



http://www.ioprogrammo.it 



060-063 Database 3-03-2005 16:23 Pagina 62 



DATABASE T ■ ComprendereADO.NET 



La guida definitiva per comprendere a fondo ADO 







Visual Basic -Net 



CI 



3 



L'ultimo articolo che ci aiuterà ad interagire con i database, 
utilizzando gli strumenti di sviluppo proposti da Visual Basic .Net 
2003. Impareremo come salvare, cancellare e modificare i dati 




Utilizza questo spazio per 
le tue annotazioni 




La prima azione da eseguire quando si vuole 
utilizzare una fonte dati è quella di aprire 
una connessione verso quest'ultima, ciò 
significa creare un oggetto SqlConnection, impo- 
stare la stringa di connessione, tramite la pro- 
prietà ConnectionString, ed aprire la connessione 
tramite il metodo Open. Per operare in modalità 
connessa, questi punti devono essere eseguiti 
soltanto alla partenza dell'applicazione, mentre 
alla fine dell'applicazione si deve chiudere la 
connessione tramite il metodo Close. Per operare 
in modalità disconnessa, invece, i punti prece- 
denti devono essere eseguiti ogni volta che si 
deve accedere al database. In pratica, ogni volta 
che si deve accedere ad un database si devono 
scrivere le seguenti istruzioni: 

Dim ObjConnection As New SqlConnectionQ 

ObjConnection. ConnectionString = "Initial 

Catalog = MiaRubrica;Data 

Source=localhost; Integrateci Security=SSPI;" 

ObjConnection .OpenQ 

'operazioni su database 

ObjConnection. CloseQ 



L'OGGETTO 
SQLCOMMAND 

Per interagire con un database, VB.Net mette a di- 
sposizione l'oggetto SqlCommand. L'oggetto Sql- 
Command deve essere associato ad un oggetto Sql- 
Connection, preventivamente connesso alla sorgen- 
te dati, e può contenere una query di selezione (per 
leggere i dati dal database) o una query d'azione (per 
aggiornare i dati), impostata tramite la proprietà 
CommandText. 

Dopo aver impostato l'oggetto SqlCommand, ed 
aver impostato la query mediante la proprietà Com- 
mandText, si deve utilizzare uno dei relativi metodi 
Execute: 



• ExecuteNonQuery si utilizza per inviare una 
query d'azione, e restituisce il numero di record 
coinvolti. Permette attività di manipolazione di 
dati, corrispondenti alle istruzioni SQL di Insert, 
Update e Delete. 

• ExecuteReader si utilizza per inviare una query 
di selezione, e restituisce l'oggetto DataReader 
che consente di accedere al set dei risultati (re- 
sultset). 

• ExecuteScalar si utilizza per inviare una query di 
selezione, e restituisce un singolo valore risulta- 
to di un'istruzione Select (da usare, ad esempio, 
se il risultato è il frutto di query con clausole di 
aggregazione come count o sum). 

L'oggetto SqlCommand espone diverse proprietà, 
tra queste: 

• CommandText permette di impostare l'istruzio- 
ne SQL della query o la stored procedure da ese- 
guire sull'origine dati. 

• CommandType permette di impostare il valore 
che indica in che modo interpretare il tipo di 
query impostato nella proprietà CommandText, 
può assumere i valori: Text, StoredProcedure 

• Connection rappresenta l'oggetto SqlConnec- 
tion associato all'istanza corrente dell'oggetto 
SqlCommand. 

• CommandTimeout permette di impostare il 
tempo di attesa (espresso in secondi) trascorso il 
quale l'esecuzione della query viene annullata e 
viene sollevata un'eccezione. Per default il suo 
valore è pari a 30 secondi. 

• Transaction rappresenta l'oggetto Transaction 
corrispondente alla transazione in cui viene ese- 
guito l'oggetto SqlCommand. 

• Parameters contiene la collezione di tutti i para- 
metri principali associati all'oggetto SqlCom- 
mand. 

Sono inoltre disponibili ulteriori metodi: 



► 62 /Aprile 2005 



http://www.ioprogrammo.it 



060-063 Database 3-03-2005 16:23 Pagina 63 



Comprendere ADO.NETl T DATABASE 



Cancel tenta di annullare l'esecuzione dell'og- 
getto SqlCommand. 

CreateParameter crea un oggetto Parameter 
associato al comando parametrico in questione. 
ResetCommandTimeout reimposta la proprietà 
CommandTimeout al valore predefinito (30 se- 
condi). 



INSERIRE O MODIFICARE 
UNA PERSONA 

Per eseguire una query di azione sul database, tipi- 
camente si deve: 

• Creare un oggetto SqlCommand con le proprietà 
fondamentali CommandText e SqlConnection. 

• Eseguire il comando Sql tramite il metodo Exe- 
cuteNonQuery, che restituisce il numero di re- 
cord coinvolti dall'istruzione. 

Inseriamo, ad esempio, una nuova persona nel data- 
base MiaRubrica. 

La prima operazione è quella di costruire la stringa 
corrispondente all'istruzione Sql di inserimento 
(Insert) 

Dim QuerySql As String 

QuerySql = "INSERT INTO Persona (CodicePersona, 

Nome, Cognome, NumeroTelefono)VALUES 

( 1, 'Federica', 'Buono', '09888888')" 

Successivamente si deve creare un oggetto SqlCom- 
mand ponendo la proprietà CommandText pari alla 
stringa che definisce la query, e la proprietà SqlCon- 
nection pari all'oggetto objConnection creato nell'e- 
sempio precedente: 

Dim ObjCommand As New SqlCommand(QuerySql, 

ObjConnection) 

Infine si deve eseguire il comando Sql tramite il me- 
todo ExecuteNonQuery, che restituisce il numero di 
record coinvolti dall'istruzione: 

Dim NumeroRecord As Integer 

NumeroRecord = ObjCommand. ExecuteNonQuery() 

Seguendo lo stesso schema possiamo modificare un 
record della tabella persona, costruendo la stringa 
corrispondente all'istruzione Sql di aggiornamento 
(update) 

Dim QuerySql As String 

QuerySql = "update Persona set Nome ='Sara', 

Cognome= 'Buono', NumeroTelefono='5556666' 

where CodicePersona = l" 

Dim ObjCommand As New SqlCommand(QuerySql, 



ObjConnection) 

Dim NumeroRecord As Integer 

NumeroRecord = ObjCommand. ExecuteNonQuery() 

Per eliminare una persona, si deve seguire sempre lo 
stesso schema utilizzando l'istruzione Sql di cancel- 
lazione (delete Persona where CodicePersona-1). 
Quando si effettuano operazioni di INSERT, UPDA- 
TE e DELETE sulle tabelle del database, diventa con- 
veniente utilizzare l'oggetto SqlCommand con le 
Stored Procedure 




LE STORED PROCEDURE 

Le stored procedure sono degli oggetti di database, 
simili a dei file batch di istruzioni T-Sql, che possono 
essere riutilizzati e richiamati avvalendosi semplice- 
mente del nome della stored procedure stessa. Sono 
spesso utilizzate come contenitore per la logica di 
business di un applicazione che utilizza database. 
La manipolazione di dati è senz'altro il punto in cui 
le stored procedure mostrano, la più ampia utilità. 
Tra i vantaggi del loro utilizzo, è da segnalare la velo- 
cità di esecuzione delle varie istruzioni, infatti la pri- 
ma volta che queste vengono utilizzate, si forma un 
"piano di esecuzione" della stored procedure che al 
successivo accesso risulterà molto più rapido nell'e- 
secuzione dello script. Tutto questo è molto più ra- 
pido rispetto all'esecuzione delle singole istruzioni 
che avrebbero un piano d'accesso ripetuto per ogni 
istruzione. Le stored procedure comunicano, con 
l'applicazione che esegue le chiamata, tramite i pro- 
pri parametri. I parametri di una stored procedure 
sono analoghi agli argomenti di una routine VB e 

L'jMiMlb/'¥«M^MI=LHLrr 



E MODALITÀ DISCONNESSA 



Per interrogare il 
database e leggere i 
dati si può utilizzare 
anche il metodo 
ExecuteScalar. Il 
metodo ExecuteScalar 
consente di eseguire in 
modo efficiente una 
query che restituisce 
un unico valore scalare, 
per questo può essere 
utilizzato per leggere il 
risultato di f un-zioni di 
aggregazione quali ad 
esempio Max o Sum. 



La domanda: "è me- 
glio operare in modali- 
tà connessa oppure in 
modalità disconnes- 
sa?" è da sempre og- 
getto di discussioni 
filosofiche tra svilup- 
patori, cerchiamo di 
capire il perché. Nelle 
tradizionali applicazio- 
ni client/server, si sta- 
bilisce una connessio- 
ne ad un database 
all'avvio dell'applica- 
zione e si mantiene 
attiva durante tutto il 
ciclo di vita dell'appli- 
cazione. Questo ap- 
proccio diminuisce il 
tempo di attesa delle 
operazioni sul databa- 
se poiché elimina il 



tempo necessario alla 
connessione, ma in al- 
cuni casi non è possibi- 
le da utilizzare (Risorse 
di sistema limitate. 
Gestione limitata di 
connessioni simulta- 
nee del database. Ap- 
plicazioni web). In mo- 
dalità disconnessa, in 
pratica, si apre una 
connessione, solo 
quando serve, si 
estrae un blocco di da- 
ti, si memorizza sul 
client e quindi si chiu- 
de la connessione per 
rilasciare le risorse la- 
to server ad essa asso- 
ciate. Dopo aver cari- 
cato i dati sul client, è 
possibile utilizzarli per 



eseguire qualsiasi tipo 
di elaborazione, come 
per esempio aggiunge- 
re nuovi record oppure 
modificare o eliminare 
quelli esistenti. Una 
volta che sono termi- 
nate le opportune 
elaborazioni sui dati, 
si riapre la connessio- 
ne, si scaricano i dati 
sul server e si richiude 
di nuovo. Le applica- 
zioni sono quindi con- 
nesse al database solo 
il tempo necessario 
per recuperare o ag- 
giornare i dati. Di con- 
tro aprire e chiudere la 
connessione significa 
maggiore tempo di 
attesa. 



http://www.ioprogrammo.it 



Aprile 2005/ 63 ► 



060-063 Database 3-03-2005 16:24 Pagina 64 



DATABASE T ■ ComprendereADO.NET 




Per mantenere il codice 
il più compatto possi- 
bile, si può utilizzare 
l'istruzione Imports 
che semplifica l'acces- 
so alle classi, elimi- 
nando la necessità di 
digitare in modo espli- 
cito il nome completo 
del namespace che le 
contiene. Le istruzioni 
Imports devono sem- 
pre essere scritte nella 
parte superiore del file 
nel quale si vogliono 
utilizzare, prima di 
qualunque altro codi- 
ce. Per queste ragioni, 
in tutti gli esempi di 
codice, è ragionevole 
assumere l'inserimento 
delle seguenti istruzio- 
ni Imports: 



Imports System .Data 

Imports System. Data 

.SqlClient 



possono essere utilizzati come variabili standard nel 
linguaggio di programmazione Transact-SQL. I pa- 
rametri devono iniziare con il carattere @ e possono 
essere di input e di output, attraverso i parametri di 
output è possibile stabilire come è terminata l'ese- 
cuzione di una stored procedure. La creazione di 
una stored procedure avviene tramite l'istruzione 
CREATE PROCEDURE e consta di una parte dichia- 
rativa, ed una parte in cui viene specificato il codice 
T-Sql. La parte dichiarativa iniziale, contiene il nome 
della stored procedure e la dichiarazione dei para- 
metri, facoltativi, che si occupano di interfacciare la 
stored procedure con l'applicazione esterna. La 
seconda parte della stored procedure, cioè quella 
che contiene il codice T-Sql, viene introdotta dalla 
parola chiave AS che si occupa appunto della sepa- 
razione tra la dichiarazione dei parametri ed il suc- 
cessivo codice T-Sql. Ad esempio, la stored procedu- 
re che esegue l'inserimento di un record nella tabel- 
la Persona, si può scrivere: 



CREATE PROCEDURE [insert 


_Persona_l] 


(@CodicePersona_ 


1 [int], 


@Nome_2 


[varchar](50), 


@Cognome_3 


[varchar](50), 



@NumeroTelefono_4 [varchar](20)) 

AS INSERT INTO [MiaRubrica].[dbo]. [Persona] ( 
[CodicePersona], [Nome], [Cognome], [NumeroTelefono]) 

VALUES 

( @CodicePersona_l, @Nome_2, 

@Cognome_3, @NumeroTelefono_4) 



UTILIZZARE 

LE STORED PROCEDURE 

Siamo pronti per utilizzare una stored procedure in 
VB.Net. Tipicamente si deve utilizzare l'oggetto Sql- 
Command impostando: 

• La proprietà CommandText al nome della Sto- 
red Procedure 

• La proprietà CommandType al valore Stored- 
Procedure 

Ad esempio, per eseguire la Stored Procedure che si 
occupa di inserire una nuova persona nel database, 
possiamo scrivere: 

Dim ObjCommand As SqlCommand 



CREAZIONE GUIDATA STORED PROCEDURE 

Ecco i passi necessari per creare le Stored Procedure di inserimento, modifica 
e cancellazione su una tabella in SQL Server 2000 



r- 1 **™""™' 



Hffi 



s&nasa 



ti • L_ I _ i I I R" - . 



■s m &r 

m % % 



IÉ © □ 




QLa prima operazione da compiere è quella 
di espandere il ramo del Server fino alla 
cartella Database e selezionare il Database 
d'esempio (MiaRubrica) 



H Dalla finestra Seleziona Procedura guidata, 
si deve espandere la voce: Database e 
selezionare l'opzione: Creazione guidata stored 
procedure 



4= SI ff D 1» 



B 



S 



Data Transfer mation Si 

■ '.'. il .: ■ i ■'■ I. 

SOL Qlwv Analyzer 
SQL Profller 

Gese"8Xnpr SQL... 



Strumenti eà' 

.: '. 



» _l Data Trans! i 



fa' ^ 




Selezionare il menu: 
Strumenti/EProcedure Guidate 



Dalla schermata di ingresso si deve cliccare 
su Avanti 



► 64 /Aprile 2005 



http://www.ioprogrammo.it 



060-063 Database 3-03-2005 16:24 Pagina 65 



Comprendere ADO.NET ■ T DATABASE 



ObjCommand = New SqlCommand("insert_Persona_l", 

ObjConnection) 

ObjCommand. CommandType = 

CommandType.StoredProcedure 

Naturalmente le istruzioni appena scritte non sono 
sufficienti, poiché dobbiamo valorizzare i campi 
della tabella persona, per questo scopo possiamo 
utilizzare i parametri. L'oggetto SqlCommand può 
contenere una collezione di oggetti SqlParameter 
che rappresenta ognuno un diverso parametro della 
stored procedure. Il nome del parametro deve corri- 
spondere al nome definito nella Stored Procedure e 
viene passato come primo argomento al costruttore 
dell'oggetto Parameter. In generale, il tipo di ogni 
oggetto Parameter deve corrispondere a quello del 
parametro accettato dalla stored procedure. È possi- 
bile passare il tipo come secondo argomento al co- 
struttore dell'oggetto Parameter utiliz-zando un va- 
lore enumerato SqlDbType che specifica i tipi di dati 
SQL Server. Come terzo argomento del costruttore è 
possibile passare la dimensione del parametro. 
Infine tramite la proprietà Value si può assegnare un 
valore al parametro. Continuando l'esempio prece- 
dente, per valorizzare i parametri della Stored Pro- 
cedure di inserimento, si può scrivere: 

Dim spPar As SqlParameter 

spPar = ObjCommand. Parameters.Add( 

"@CodicePersona_l", SqlDbType.Int, 4) 

spPar.ValueQ = 1 

spPar = ObjCommand. Parameters.Add("@Nome_2", 

SqlDbType.VarChar, 50) 

spPar.ValueQ = "Federica" 

spPar = ObjCommand. Parameters.Add( 

"@Cognome_3", SqlDbType .Va rChar, 50) 

spPar.ValueQ = "Buono" 

spPar = ObjCommand. Parameters.Add( 

"@NumeroTelefono_4", SqlDbType. Va rChar, 20) 



spPar.ValueQ = "05588888888" 

Infine, come negli esempi precedenti, si esegue l'i- 
struzione sul database: 

Dim NumeroRecord As Integer 

NumeroRecord = ObjCommand. ExecuteNonQueryQ 

Quando si utilizzano le stored procedure occorre te- 
ner conto della direzione di ciascun parametro. Se si 
invoca una stored procedure, che restituisce un va- 
lore attraverso un argomento, è necessario imposta- 
re la proprietà Direction ad InputOutput oppure ad 
Output. Per default tutti i parametri vengono creati 
come parametri di input perciò, in questo caso, non 
è necessario impostare la proprietà Direction. 



INTERROGARE 
IL DATABASE 

Per interrogare il database e leggere i dati si deve: 



• Creare un oggetto SqlCommand come abbiamo 
visto in precedenza. 

• Eseguire la query Sql tramite il metodo Execu- 
teReader, ed assegnarlo ad un ogget-to SqlData- 
Reader per leggere il set dei risultati una riga per 
volta. 

Ad esempio, per eseguire una ricerca di tutte le per- 
sone presenti in MiaRubrica, si può scrivere: 

Dim QuerySql As String 

QuerySql = "select * from persona" 

Dim ObjCommand As New SqlCommand(QuerySql, 

ObjConnection) 

Dim ObjReader As SqlDataReader = 

ObjCommand. ExecuteReaderQ 




La proprietà 
ConnectionString 
permette di impostare 
la stringa di 
connessione al 
database. La stringa di 
connessione consente 
di definire il nome del 
database di origine ed 
altri parametri 
necessari a stabilire la 
connessione iniziale, 
delimitati da punto e 
virgola. Ad esempio 
l'attributo Data Source 
può assumere il valore 
localhost nel caso 
dobbiamo connetterci 
ad SQL Server sulla 
macchina locale, ma in 
generale deve 
contenere il nome del 
computer sul quale è 
installato il database. 



Creazione guidata stored procedure - (local)\MiaRi 



Seleziona database 

Selezionare il database in cui archiviare le stored procedu 



Nome ci; tei: ase: 



Qln questa maschera è necessario 
selezionare il database su cui si 
devono generare le Stored Procedure 
dal menu a tendina. Il database 
MiaRubrica dovrebbe essere 
selezionato di default. Per confermare 
la scelta è sufficiente cliccare su Avanti. 




L 



Q Selezionare le Stored Procedure 
che si vogliono creare su ogni 
tabella del database. Nel nostro caso 
sarà presente soltanto la tabella 
Persona su cui dovremo selezionare i tre 
tipi di Stored Procedure da creare 
(Inserisci, elimina, aggiorna) 





fa 


Completamento della Creazione guidata stored 
procedure 

•itored procedure indie;?» li seguito, ' i i > li o rnodiiicare 
una itored procedure, lare clic eu Modifica 






llr 




L 




1 -._! i i II II 
delete_Persona_1 Elimina una i 












Modifica... 














< Indietro | Fine | Annulla | 







B Dall'ultima finestra si possono 
modificare il nome e la struttura 
delle stored procedure. È sufficiente 
selezionare la stored procedure e 
cliccare sul tasto modifica. Infine 
cliccando sul tasto Fine le tre stored 
procedure verranno create nel Database 



http://www.ioprogrammo.it 



Aprile 2005/ 65 ► 



060-063 Database 3-03-2005 16:24 Pagina 66 



DATABASE T 



Comprendere ADO.NET 




Script SQL della 

tabella persona in cui 

CodicePersona è la 

primary key 



CREATE TABLE 

[dbo]. [Persona] ( 

[CodicePersona] [int] 

NOT NULL , 

[Nome] [varchar] (50) 

NULL, 

[Cognome] [varchar] 

(50) NULL, 

[NumeroTelefono] 

[varchar] (20) NULL 

) ON [PRIMARY] 



Analizziamo in dettaglio come utilizzare l'oggetto 
SqlDataReader per leggere il set di risultati ottenuto. 



L'OGGETTO 
SQLDATAREADER 

L'oggetto SqlDataReader viene utilizzato per leggere 
un set dei risultati di tipo forward-only da un data- 
base SQL Server, a seguito di una query d'interroga- 
zione. A differenza degli oggetti visti in precedenza 
non è possibile utilizzare un costruttore per creare 
un oggetto SqlDataReader, ma è invece necessario 
chiamare il metodo ExecuteReader dell'oggetto Sql- 
Command Tra le proprietà ed i metodi esposti dal- 
l'oggetto SqlDataReader segnaliamo: 

FieldCount contiene il numero di colonne del 
record corrente. 

IsClosed contiene un valore, pari a True, se il 
DataReader è chiuso. 

RecordsAffected contiene il numero di record 
modificati, inseriti o eliminati dall'esecuzione 
dell'istruzione SQL. 

Close chiude l'oggetto SqlDataReader e rilascia 
le risorse allocate. 

GetName contiene il nome della colonna con 
l'indice specificato. 

IsDbNull contiene un valore, pari a True, se la 
colonna contiene valori nulli. 
Read sposta l'oggetto SqlDataReader al record 
successivo. Restituisce un valore pari a True se 
sono presenti altri record da elaborare, oppure 
False se si è arrivati alla fine del set dei risultati 
• GetValue contiene il valore della colonna con 
l'indice specificato nel suo formato nativo 

Al posto del metodo GetValue è possibile utilizzare 
uno dei numerosi metodi Get fortemente tipizzati, 
come GetString o GetDecimal. In pratica c'è un 
metodo Get per ogni tipo di dati gestito da VB oppu- 
re un metodo GetSql per ogni tipo di dati gestito da 
Sql Server. Questi metodi particolari dovrebbero 
essere sempre adottati, in quanto evitano gli errori 
di conversione provocati dalla perdita di precisione 
e generano codice più veloce. 



UTILIZZARE L'OGGETTO 
SQLDATAREADER 

Per iterare sui singoli record di un set di risultati, uti- 
lizzando l'oggetto SqlDataReader, è sufficiente: 

• invocare il metodo Read per avanzare al record 
successivo nel set di risultati 

• verificare il relativo valore di ritorno per control- 
lare se esistono altri risultati (nel caso sia pari a 



True) oppure si è arrivati alla fine e non c'è nes- 
sun' altra riga da leggere (se è False). 

Grazie al funzionamento del metodo Read è possibi- 
le creare un ciclo While.. End While basato sull'og- 
getto SqlDataReader. Per completare l'esempio pre- 
cedente, in cui si cercano tutti le persone presenti in 
MiaRubrica, possiamo scrivere il seguente codice 
che mostra un messaggio per ogni persona in archi- 
vio: 

Dim CodicePersona, Nome, Cognome, NumeroTelefono 

As String 

While ObjReader.ReadQ 

CodicePersona = ObjReader.GetInt32(0) 

Nome = ObjReader.GetString(l) 

Cognome = ObjReader.GetString(2) 

NumeroTelefono = ObjReader.GetString(3) 

MessageBox.Show(CodicePersona &.""&. Nome & 

" " & Cognome &.""&. NumeroTelefono) 

End While 

Mentre si utilizza l'oggetto SqlDataReader, non è 
possibile eseguire alcuna operazione sull'oggetto 
SqlConnection associato, per questo è importante 
chiudere l'oggetto SqlDataReader quando non esi- 
stono più righe da elaborare, in modo da rilasciare le 
risorse (lato client e lato server) e rendere la connes- 
sione nuovamente disponi-bile per altri comandi: 

ObjReader.Close() 



CONCLUSIONI 

Esistono altri metodi per l'accesso ai dati. Uno di 
questi é rappresentato dagli oggetti SqlDataAdapter 
e Dataset tramite i quali si realizza una sorta di 
approccio disconnesso ai dat, tale che la view dei 
dati viene copiata in locale in una forma statica; ven- 
gono effettuate tutte le modifiche nexessarie, e una 
volta compiute le varie operazioni il database viene 
risincronizzato con quello originale. Delle due 
modalità fornite da ADO.NET per la gestione dei 
dati, i resultset forward-only di sola lettura sono 
quelli che consentono di ottenere le prestazioni 
migliori. Ciò è dovuto al fatto che il DataSet non 
mantiene attiva una connessione alla sua origine 
dati per tutto il tempo in cui l'oggetto esiste, come al 
contrario accade per l'oggetto SqlDataReader. 
Mentre SqlDataReader non è scalabile come la com- 
binazione SqlDataAdapter/ DataSet, può fornire 
migliori prestazioni per un'origine dati remota dal 
momento che essa restituisce dati come un cursore 
forward-only in sola lettura. 

A voi stabilire quale modalità utilizzare a seconda 
dei casi. 

Luigi Buono 



► 66 /Aprile 2005 



http://www.ioprogrammo.it 



VISUAL BASIC T 



Le funzioni non documentate di Visual Basic 



Utilizzare Shell32.dll in VB 



Undocumented 
Shell32 library 

Vediamo come sfruttare alcune funzionalità non documentate in VB 
Mostreremo le dichiarazioni e gli esempi d'uso delle funzioni che 
ci consentono di dialogare con il cuore del sistema operativo 




Ci CD □ WEB 



^ 



wmmivmm 



J 




n.i.i.wmiw.m4fl 

p^ Conoscenze di base di 
Lì)) Windows, Visual Basic 



Windows XP, 
Visual Basic 6.0 



IBI 



Tempo di realizzazione 



fP% fy\ f Vi f Vi f Vi 



Per shell s'intende quella componente del si- 
stema operativo attraverso la quale è possibi- 
le compiere la maggior parte delle operazioni 
che comuni che "investono" normalmente la vita di 
tutti: apertura di file, navigazione tra le directory, 
configurazione di stampanti, creazione di collega- 
menti sul desktop, ecc. La shell, organizza tutto que- 
st'insieme d'entità all'interno di una struttura gerar- 
chica, meglio conosciuta con il nome di Namespace. 
La Shell Namespace possiamo immaginarla come 
equivalente al noto filesystem, malgrado consenta 
anche la gestione di oggetti speciali come i virtual 
folder. In questo contesto, è necessario adottare una 
strategia d'identificazione diversa da quella utilizza- 
ta dal "semplice" filesystem ed è per questo che si 
parla diitemID. 



LA FUNZIONE 
SHRUIMDIALOGO 



La prima funzione che analizzeremo è la SHRun- 
DialogO, una "undocumented function" la cui sin- 








CB ABID 


LUNQJliZZA VARJADILC 




.' nv 1 1 s 


ITEM 1D LIST 




IcB ABID CB ABID CB ABID 


2 

bn| 


A 


ITEM ID 1 ITEM II 


3 2 ]TEM ID 3 

2 BYTES NULLI - 




-PIDL 







tassi in Visual Basic è la seguente: 

Public Declare Function SHRunDialog Lib "shelll32" 

Alias "#61" (ByVal hWnd As Long, ByVal hlcon 

As Long, ByVal sPath As String, ByVal sTitle 

As String, ByVal sPrompt As String, ByVal uFIags 

As Long) As Long 

Scopo della funzione è quello di mostrare a video 
una finestra di dialogo attraverso la quale consenti- 
re l'avvio di un determinato programma. Per perso- 
nalizzare il funzionamento e la modalità di richiesta 
all'utente, viene sfruttato in particolare l'ultimo 
parametro, uFIags che opportunamente settato, 
permette di nascondere il pulsante Sfoglia oppure la 
lista dei programmi avviati (MRU- Most Recently 
Used). Di seguito un piccolo esempio che imple- 
menta queste funzionalità: 

Private Sub cmdRunDialog_Click() 
Dim uFIag As Long 
Dim sTitle, sPrompt, sLw, SysDir As String 

If Optionl(0).Value=True Then 

SHRunDialog hWnd,Q,0,vbNullString,vbNullString,0 

Else 

If Checkl(0).Value=l Then uFlag=&H3 Else 

uFlag=&H2 

If Checkl(l).Value=l Then 



SysDir=Space$(256) 



Ret=GetSystemDirectory(SysDir,Len(SysDir)) 
If Reto Then _ 



SysDir=Left$(SysDir, 



Len(Trim$(SysDir))-l)&"\Shell32.dll" 

hlcon = ExtractIcon(App.hInstance,SysDir,46) 

Else 

hlcon=0 

End If 



sTitle=txtSHRunDialog.Text 



Fig. 1: Item ID, item ID List e PIDL 



sPrompt=txtPrompt.Text 



► 66 /Aprile 2005 



http://www.ioprogrammo.it 



Le funzioni non documentate di Visual Basic ■ T SISTEMA 



sl_w=txtCercaIn.Text 



'Se il sistema operativo è Windows NT like, 



'allora trasforma tutte le stringhe 



'utili in formato Unicode 



If IsWinNT Then 



sTitle=StrConv(sTitle,vbL)nicode) 



sPrompt=StrConv(sPrompt,vbL)nicode) 



sl_w=StrConv(sl_w,vbUnicode) 



End If 



'Avvia la finestra di dialogo 



SHRunDialog 



hWnd,hIcon,sl_w,sTitle,sPrompt,uFlag 



End If 



End Sub 

Un dettaglio importante e che ritroveremo spesso 
all'interno delle restanti procedure, è la preventiva 
conversione in Unicode delle stringhe passate alle 
API della Shell32 qualora il sistema operativo riscon- 
trato sia Windows NT-like. 



GLI SPECIAL FOLDERS 

Abbiamo visto che la Shell consente di gestire diver- 
si tipi di oggetti, tra i quali anche quelli cosiddetti 
virtuali come la cartella dei documenti e quella delle 
stampati. Questo genere di oggetti fa parte di quel- 
l'insieme definito come cartelle speciali tra le quali, 
oltre a quelli definiti virtuali, ve ne sono altri definiti 
"standard" come System o Program Files. Ovvia- 
mente la lista è molto più lunga e possiamo ricavare 
il reale percorso fisico sul disco rigido attraverso 
TAPI SHGetSpecialFolderLocationO e SHGetPath- 
FromlDListO le cui sintassi VB sono rispettivamente: 

Public Declare Function SHGetSpecialFolderLocation Lib 
"shell32" (ByVal hwndOwner As Long, ByVal nFolder 
As Long, PIDL As Long) As Long 
Public Declare Function SHGetPathFromIDList Lib 

"Shell32.dll" Alias "SHGetPathFromIDListA" (ByVal 
PIDL As Long, ByVal pszPath As String) As Long 

La prima consente di ottenere un puntatore ad un 
oggetto di tipo ITEMIDLIST, mentre la seconda ser- 
vendosi di questa informazione, ne ricava il percor- 
so fisico su disco rigido riportandolo all'interno del 
secondo parametro pszPath. Tralasciando i dettagli 
e volendo rendere il tutto più "semplice", è sufficien- 
te dire che i passi da compiere sono solo questi: 

• passare alla SHGetSpecialFolderLocationO la co- 
stante CSIDL (un identificativo che rappresenta 
una particolare cartella speciale). Se tutto va a 
buon fine, essa ci restituirà in PIDL il valore da 
utilizzare per la seconda chiamata; 

• passare a SHGetPathFromIDListO il valore di 
PIDL e, se tutto va bene, ci ritroveremo in psz- 



Path il percorso che volevamo. 

Di seguito un esempio su entrambe le funzioni: 

Private Sub cmbSpecialFolder_Click() 

'Visualizza il percorso completo di una cartella 

'speciale sul proprio HD 

Dim Index As Long 
Index=cmbSpecialFolder.ItemData(cmbSpecialFolder 

.Listlndex) 
If Index>-1 Then 

txtSpecialFolderPath.Text=GetSpecialFolder(Index) 

End If 




End Sub 



dove: 




Function GetSpecialFolder(CSIDL As Long) As String 


Dim sPath As String 


Dim PIDL As Long 


If SHGetSpecialFolderLocation( 

frmPrincipale.hWnd,CSIDL,PIDL) = S_OKThen 


'Se il PIDL è correttamente riportato, 


'preleva il percorso dall'ID list 


sPath=Space$(MAX_PATH) 


If SHGetPathFromIDList( 

ByVal PIDL,ByVal sPath) Then 



LE COSTANTI CSIDL 



Di seguito ecco alcune costanti CSIDL: 



PER SAPERNE 
DI PIÙ 



Maggior informazioni 
possono essere 
recuperate sul sito della 
Microsoft al link 

htt p://msd n . m icrosoft.com/ 
library/default.asp?url=/ 
library/en-us/dnanchor/ 
html/anch winshell.asp 



CSIDL_ADMINTOOLS 


(user name>\Start Menu\Programs\ 
Administrative Tools) 


CSIDL_APPDATA 


(Application Data, new for NT4) 


CSIDL_COMMON_ADMINTOOLS 


(Ali Users\Start Menu\Programs\ 
Administrative Tools) 


CSIDL_COMMON_APPDATA 


(Ali Users\Application Data) 


CSIDL_COMMON_DOCUMENTS 


(Ali Users\Documents) 


CSIDL_COMMON_PROGRAMS 


(Programs folder (under Start menu in AH 
Users profile)) 


CSIDL_DESKTOP 


(Desktop (namespace root)) 


CSIDL DESKTOPDIRECTORY 


(Desktop folder) 


CSIDL FAVORITES 


(Favorites folder) 


CSIDL_FLAG_CREATE 


(new for Win2K, or this in to force 
creation of folder) 


CSIDL_FONTS 


(Fonts virtual folder) 


CSIDL_HISTORY 


(History folder) 


CSIDL_INTERNET_CACHE 


(Internet Cache folder) 


CSIDL_MYPICTURES 


(My Pictures, new for Win2K) 


CSIDL NETHOOD 


(Network Neighborhood directory) 


CSIDL_PERSOIMAL 


(Personal folder) 


CSIDL_PROGRAM_FILES 


(C:\Program Files) 


CSIDL_PROGRAM_FILES_COMMON 


(C:\Program Files\Common) 


CSIDL_PROGRAMS 


(Programs folder (under Start menu); My 
Documents) 


CSIDL_RECENT 


(Recent folder) 


CSIDL_SENDTO 


(SendTo folder) 


CSIDL_STARTMENU 


(Start menu) 


CSIDL_STARTUP 


(Startup folder) 


CSIDL_SYSTEM 


(GetSystem Directory 0) 


CSIDL_TEMPLATES 


(Templates folder) 


CSIDL_WIIMDOWS 


(GetWindowsDirectoryO) 



http://www.ioprogrammo.it 



Aprile 2005/ 67 ► 



VISUAL BASIC T 



Le funzioni non documentate di Visual Basic 




GetSpecialFolder=l_eft( 

sPath, InStr(sPath,Chr$(Q))-l) 

End If 

'Libera il PIDL 



Cali CoTaskMemFree(PIDL) 



End If 




I TUOI APPUNTI 



End Function 



LE FUNZIONI 

SHRestartSystemIVIBQ 
E SHShutDownDialogO 

Le due funzioni che stiamo per mostrare sono molto 
simili tra loro e per questa ragione le tratteremo al- 
l'interno dello stesso paragrafo. La SHRestartSystem- 
MB() è una funzione non documentata ed il suo 
scopo è semplicemente quello di effettuare il riavvio, 
il logoff, ecc. . . del sistema. 
La sua sintassi è la seguente: 

Public Declare Function SH Resta rtSystem MB Lib 

"shell32" Alias "#59" (ByVal hOwner As Long, ByVal 
sPrompt As String, ByVal uFIags As Long) As Long 



Utilizza questo spazio per dove* 

le tue annotazioni 



hOwner: handle dell' owner window (tipicamen- 



LA STRUTTURA SHFILEOPSTRUCT 



Di seguito sono mostrati i principali valori che può assumere l'item fFlags 
della struttura SHFILEOPSTRUCT 



FOF CREATEPROGRESSDLG 


La finestra di dialogo è visibile. 


fof_multidestfii.es 


Indica che pTo specifica destinazioni 
multiple per i file. 


FOF_CONFIRMMOUSE 


Non implementato 


FOF SILENT 


La finestra di dialogo non è visibile. 


FOF_RENAMEONCOLLISION 


Se nella directory di destinazione, esiste 
un file con un nome identico al sorgente, 
viene creato un nuovo file del tipo 
"Copiai di ..." 


FOF NOCONFIRMATION 


Non chiede conferma all'utente 


FOF_WANTMAPPINGHANDLE 


La funzione SHFileOperation riempe 
hNameMappings (leggere più avanti) 


FOF_ALLOWUNDO 


Preserva le informazioni per un 
eventuale UNDO. 


FOF_FILESONLY 


Nel caso si specifichi *.* effettua 
l'operazione solo sui file e ne migliora le 
prestazioni. 


FOF_SIMPLEPROGRESS 


La finestra di dialogo è visibile, ma non 
vengono visualizzati i nome dei file. 


FOFJMOCONFIRMMKDIR 


Nel caso sia necessario creare una nuova 
directory, il sistema non chiede conferma. 


FOF NOERRORUI 


Nessun messaggio in caso di errori 


FOFJMORECURSION 


Nessuna ricorsione nelle sottodirectory. 
L'operazione avviene solo a livello di 
directory corrente 


FOF_NOCOPYSECURITYATTRIBS 


Non copia gli attributi di sicurezza 


FOF_NO_CONNECTED_ELEMENTS 


(vedi riquadro 1 Connecting File) 


FOF_WANTNUKEWARNING 


Avverte l'utente con un warning nel caso 
si stia eliminando un file (non nel Cestino). 


FOFJMORECURSEREPARSE 


Nessuna ricorsione sui reparse point 



te la form principale); 

• sPrompt: testo aggiuntivo che apparirà a video 
per la conferma dell'operazione; 

• uFIags: costante che identifica il tipo di opera- 
zione da effettuare. 

Vediamo subito il codice relativo a questa funziona- 
lità: 



Private Sub cmdRestartDialog_Click() 


Dim ExtraMsg As String 


Dim uFIag As Long 


ExtraMsg = TxtRestartPrompt 


If IsWinNT Then ExtraMsg = StrConv(ExtraMsg, 
vbUnicode) 


Select Case cmbRestartOp.Listlndex 


Case 


uFIag = EWX_LOGOFF 


Case 1 


uFIag = EWX_SHUTDOWN 


Case 2 


uFIag = EWX_REBOOT 


Case 3 


uFIag = EWX_FORCE 


Case 4 


uFIag = EWX_POWEROFF 


End Select 


If SHRestartSystemMB(frmPrincipale.hWnd, 

ExtraMsg, uFIag) = vbYes Then 


MsgBox "OK... alla prossima volta..." 


End If 


End Sub 



J 



Anche la SHShutDownDialogO non è documentata 
e la sua sintassi risulta essere la seguente: 

Public Declare Function SHShutDownDialog Lib 

"shell32" Alias "#60" (ByVal Flag As Long) As Long 

Accetta un solo parametro identificato da una delle 
costanti precedentemente utilizzate dalla SHRe- 
startSystemMBQ. Il suo unico scopo è quello di mo- 
strare la finestra di chiusura del sistema allo stesso 
modo di quanto avviene quando l'utente decidere di 
spegnere il proprio PC. 



LA FUNZIONE 

SHBrowseForFolder() 

La funzione SHBrowseForFolder() mostra a video 
una finestra di dialogo che ci consente di scorrere le 
cartelle ed i file del nostro disco rigido, con la possi- 
bilità d'impostare dei filtri sugli oggetti visualizzati e 
selezionabili. La sintassi è: 

Public Declare Function SHBrowseForFolder Lib 

"shell32" (Ipbi As BROWSEINFO) As Long 

La struttura BROWSEINFO è così dichiarata: 

Public Type BROWSEINFO 

hwndOwner As Long 



► 68 /Aprile 2005 



http://www.ioprogrammo.it 



Le funzioni non documentate di Visual Basic ■ T VISUAL BASIC 



pidIRoot As Long 



pszDisplayName As String 



IpszTitle As String 



ulFlags As Long 



Ipfn As Long 



IParam As Long 



ilmage As Long 



End Type 

In particolare, il parametro ulFlags definisce proprio 
il filtro per l'esplorazione delle cartelle. Il valore di 
questo item della struttura può essere una combina- 
zione di svariate costanti (identificate con prefisso 
BIF). Vediamo un esempio: 

Private Sub cmdBrowseFolder_Click() 
Dim iNull As Integer 
Dim IDList As Long, Result As Long 

Dim sPath As String 

Dim Brwlnf As BROWSEINFO 

'Inizializza la struttura 

With Brwlnf 

.hwndOwner=Me.hWnd 

.pszDisplayName=Space(260) 

.lpszTitle=("Shell32 API - by ioProgrammo") 

.ulFlags=BIFoption 

End With 

IDList=SHBrowseForFolder(BrwInf) 

If IDList Then 

sPath=String$(MAX_PATH,Q) 

SHGetPathFromIDList IDList,sPath 

'Libera IDList 

CoTaskMemFree IDList 

iNull = InStr(sPath,vbNullChar) 

If iNull Then 

sPath = Left$(sPath, iNull - 1) 

End If 

End If 

'Ritorna le informazioni 

txtPath.Text=sPath 

txtSelectedFolder.Text= Brwlnf. pszDisplayName 
txtIdxImage.Text=(BrwInf. ilmage) 
End Sub 



LA FUNZIONE 

SHChangeIconDialog() 

La funzione in oggetto ha la seguente sintassi: 



Public Declare Function SHChangelconDialog Lib 

"shell32" Alias "#62" (ByVal hOwner As Long, ByVal 

szFilename As String, ByVal Reserved As Long, 

Iplconlndex As Long) As Long 

La funzione non fa altro che mostrare a video una 
finestra di dialogo attraverso la quale possiamo sce- 
gliere un'icona dal file considerato ritornando l'indi- 



ce della stessa all'interno del parametro lplconldx. 



Private Sub cmdChangeIcon_Click() 



Dim FileName As String 



Dim Iconldx As Long 



Dim Smalllcon As Long, Largelcon As Long 



'Alloca il buffer 




FileName=txtIconPath&String$(MAX_PATH - Len( 

txt!conPath),0) 

x Se il sistema operativo è Windows NT-like, allora 
'converti la stringa in formato Unicode 



If IsWinNTThen FileName=StrConv( 

FileName, vbUnicode) 



IconIdx=Val(txtIconIdx) 



'Il valore di ritorno della funzione è: 



'0: l'utente ha cancellato l'operazione 



x l: selezione effettuata 



If SHChangeIconDialog( 

hWnd, FileName, 0, Iconldx) Then 



'Mostra la selezione fatta 



txtIconPath=GetStrFromBuffer(FileName) 



txt!conIdx=IconIdx 



If ExtractIconEx(FileName, Iconldx, 

Largelcon, Smalllcon, 1)>0 Then 



picSmallIcon.AutoRedraw=True 



picLargeIcon.AutoRedraw=True 



'Disegna l'icona 



DrawIconEx picSmallIcon.hDC,l,l, 
Smalllcon, 0,0,0,0,DI_NORMAL 

DrawIconEx picLargeIcon.hDC,l,l, 
Largelcon, 0,0, 0,0,DI_NORMAL 



Destroylcon Smalllcon 



Destroylcon Largelcon 



picSmallIcon.Refresh 



picSmallIcon.AutoRedraw= False 



picLargelcon.Refresh 



I CONNECTING FILE 



A partire da Windows 2000 esiste 
un'interessante particolarità lega- 
ta alle operazioni che si possono 
compiere su file e directory ossia 
esiste la possibilità di collegare ad 
un file HTML un insieme di file 
contenuti all'interno di una direc- 
tory. Così facendo, ogni qualvolta 
viene effettuata un'operazione di 
copia o spostamento sul file HTML, 
tutta la directory ad esso collega- 
to (e quindi anche i file in essa 
contenuti) subiranno lo stesso 
trattamento. Per poter sfruttare 
questa funzionalità, è sufficiente 
seguire pochi semplici passi: 

• Posizionarsi nella directory di 
prova (ad esempio Test); 

• Creare al suo interno un file 
con estensione htm o html (ad 



esempio Pippo.htm); 

• Creare una sottodirectory di 
nome uguale al file HTML, ma 
senza estensione e seguito dal 
suffisso _files (ad esempio 
Pippo_files); 

• Copiare al suo interno i file che 
vogliamo connettere. 

A questo punto, ogni operazione 
su Pippo.htm si rifletterà anche 
sui file contenuti in Test\Pippo_ 
files. Questa opzione è abilitata 
per default e può essere disabilita- 
ta attraverso registry). 
Nel caso sia attiva, ma si volesse 
operare con la funzione 
SHFileOperationO solo su alcuni 
dei file collegati, è possibile 
servirsi del f lag FOF_NO_CON- 
NECTED_ELEMENTS. 



http://www.ioprogrammo.it 



Aprile 2005/ 69 ► 



VISUAL BASIC T 



Le funzioni non documentate di Visual Basic 






picl_argeIcon.AutoRedraw= 


= False 


End If 


End If 


End Sub 



INFORMAZIONI SUI FILE 

Esistono diverse funzioni undocumented per otte- 
nere informazioni dai file. In particolare: 



• SHFileExists: ritorna un valore non nullo se il 
percorso passato come parametro è un percorso 
UNC valido; 

• SHGetPathArgs: ritorna la stringa che inizia 
dopo il primo spazio trovato all'interno del file 
specificato; 

• SHGetShortPathName: ritorna il percorso del 
file in formato "short" (ossia 8.3). 

Vediamo un semplice esempio che le utilizza tutte 



• SHGetExtension: ritorna l'estensione del file; 

• SHGetFileName: ritorna il nome del file privo 
del percorso; 

• SHPathlsRelative: ritorna un valore non nullo 
se il primo carattere è diverso da "\" (non è un 
percorso UNC) o il secondo carattere è diverso 
da":"; 

• SHPathlsExe: ritorna True se il file ha l'estensio- 
ne di un file eseguibile (.bat, exe, .com e .pif); 



Private Sub Filel_Click() 



Dim sTB As String 



'Normalizza. 



txtPaths=NormalizzaPercorso(Filel.Path)&Filel 
sTB=txtPaths 



'Visualizza le informazioni relative alla selezione fatta 

lblGetExtension = "GetExtension: 
"&GetExtension(sTB) 

lblGetFilename="GetFileName: "&GetFileName(sTB) 





UHI PROGRAMMA PER RESETTARE IL COMPUTER 

INIZIALIZZIAMO IL PROGRAMMA IMPOSTIAMO IL FILTRO DI BROWSING 






'Impostiamo a il flag 
BIFoption = 




' Valorizza il flag BIFOption in base al valore della proprietà 




' TAG del controllo selezionato/deselezionato. La proprietà Tag 
' del controllo contiene, per ogni elemento dell'array 


'Mostriamo all'avvio il pannello 


Picturel(0).ZOrder 


' CheckBIF, il corretto valore decimale da aggiungere/sottrarre. 
If CheckBIF(Index).Value = 1 Then 


'Carichiamo la lista degli special folder 


With cmbSpecialFolder 


BIFoption = BIFoption + CheckBIF(Index).Tag 


.Addltem "CSIDL_DESKTOP {desktop}" 


Else 


.ItemData(.NewIndex)=&HO 


BIFoption = BIFoption - CheckBIF(Index).Tag 


.Addltem "CSIDL_I INTERNET Internet Explorer 

(icon on desktop)" 
.ItemData(.NewIndex)=&Hl 


End If 


EV Impostiamo la variabile BIFoption servendoci della 




.Addltem "CSIDL_PROGRAMS Start Menu\Programs" 


Kfl oroorietà Tao delle checkbox. 


.ItemData(.NewIndex)=&H2 




ECC.. 
End With 




MOSTRIAMO LA FINESTRA DI DIALOGO 






' Inizializza la struttura 




'Se il sistema operativo è Windows NT-like... 


If IsWinNTThen 


With Brwlnf 


TxtRestartPrompt="ioProgrammo Restart Program" + 

vbCrLf + vbCrLf 
With cmbRestartOp 


.hwndOwner = Me.hWnd 


.pszDisplayName = Space(260) 


.IpszTitle = ("Shell32 API - by ioProgrammo") 


.Addltem "0 - EWX LOGOFF" 


.ulFlags = BIFoption 


.Addltem "1 - EWX SHUTDOWN" 


End With 


.Addltem "2 - EWX_REBOOT" 


IDList = SHBrowseForFolder(BrwInf) 
If IDList Then 
sPath = String$(MAX_PATH, 0) 


.Addltem "4 - EWX_FORCE" 


.Addltem "8 - EWX POWEROFF" 


End With 


SHGetPathFromIDList IDList, sPath 


Else 


' Libera IDList 


TxtRestartPrompt= "Attenzione...!" & vbCrLf & 


CoTaskMemFree IDList 


"Se si preme Sì, Windows chiuderà tutte le sessioni ed" & 
"vbCrLf & i programmi senza nessuna richiesta di 


iNull = InStr(sPath,vbNullChar) 


If iNullThen 


"conferma!" & vbCrLf & vbCrLf 


sPath = Left$(sPath, iNull - 1) 


With cmbRestartOp 


End If 


.Addltem "1 - EXIT senza prompt" 


End If 


.Addltem "2 - REBOOT system" 


' Ritorna le informazioni 


End With 


txtPath.Text = sPath 


End If 


txtSelected Folder. Text = BrwInf.pszDisplayName 


End Sub 


txtldxImage.Text = (Brwlnf.ilmage) 


WM Inizializziamo le variabili necessarie ed impostiamo i 
Efl valori delle listbox utilizzate nel programma. 




CV Mostriamo la finestra di dialogo filtrata e la selezione 
ti dell'utente. 





► 70 /Aprile 2005 



http://www.ioprogrammo.it 



Le funzioni non documentate di Visual Basic ■ T VISUAL BASIC 



lblIsPathRelative="IsPathRelative: 
"8JsPathRelative(sTB) 



lblIsPathExe="IsPathExe: 



"8JsPathExe(sTB) 



lblFileExists="FileExists: 



"&FileExists(sTB) 



lblGetArgs="GetArgs: 



"&GetArgs(sTB) 



lblGetShortPath = "GetShortPath: "&GetShortPath(sTB) 
End Sub 

La funzione NormalizzaPercorsoO non fa altro che 
"normalizzare" la stringa passata come parametro 
(ossia il percorso di un file), aggiungendo, se occor- 
re, un "\" al termine. 



LA FUNZIONE 
SHFILEOPERATIONO 

Una delle funzioni più interessanti della libreria 
Shell32, è la SHFileOperation(). Attraverso essa è 
possibile compiere operazioni come copia e cancel- 
lazione di file demandando la maggior parte dei 
compiti "gravosi" al sistema operativo. Non fa parte 
delle undocumented function di Shell32, ma si è 
pensato che poteva comunque essere interessante 
dare un'occhiata alle sue "capacità". 
La sintassi della funzione è la seguente: 

Declare Function SHFileOperation Lib "Shell32.dll" Alias 
"SHFileOperationA" (IpFileOp As SHFILEOPSTRUCT) 

As Long 

La funzione ritorna zero in caso di successo. Il para- 
metro IpFileOp deve riferirsi ad una struttura "vali- 
da" ed il compito di valorizzarla, ovviamente, spetta 
al programmatore. Nel caso essa punti ad una strut- 
tura nulla o con item "errati", è possibile che si veri- 
fichino risultati imprecisabili. Esistono alcuni "pic- 
coli" dettagli circa l'utilizzo della funzione SHFile- 
OperationQ ed uno di questi, molto importante, è 
quello che riguarda l'operazione d'eliminazione dei 
file. Va ricordato, infatti che se il valore di fFlags non 
"contiene" l'opzione FOF_ALLOWNDO, un'opera- 
zione siffatta porta alla cancellazione permanente 
del file o dei file oggetto dell'operazione, ossia senza 
che questi passano attraverso il Cestino. Comincia- 
mo subito col vedere un esempio sulla copia dei file: 



Function SHCopiaFile() As Long 


'Inizializza la struttura 


With SHFileOp 


.hWnd=frmPrincipale.hWnd 


.wFunc=FO_COPY 


.pFrom = FileOrigine&String$(2,0) 


.pTo=Destinazione&"\"&String$(2,0) 


.fFlags=FOF_SIMPLEPROGRESS 


'.lpszProgressTitle="Operazione ir 


corso... 
'&String$(2,0) 


End With 



SHCopiaFile=SHFileOperation(SHFileOp) 

^GESTIONE ERRORI... 

End Function 

Tutto quello che occorre fare è compilare opportu- 
namente la struttura SHFileOp (rammentando di 
valorizzare nella maniera opportuna l'item wFunc e 
di terminare con un doppio zero le stringhe pFrom e 
pTo) e richiamare la fun- 
zione passandole pro- 
prio quest'oggetto. In 
questa funzione, così co- 
me nelle restanti, non so- 
no stati gestiti gli errori 
solo per non diminuire la 
leggibilità del codice, ma 
chiunque può migliorare 
questa e le restanti com- 
pletando questo "pezzo 
mancante". Per maggiore 
chiarezza, mostriamo la 
funzione che si occupa di 
gestire l'eliminazione di 
un file: 





Fig. 2: Le API per ottenere informazioni sui file in 
azione 



Public Function SHEIiminaFile() As Long 
'Inizializza la struttura 
'(l'item pTo può essere ignorato) 



With SHFileOp 



.hWnd=frmPrincipale.hWnd 



.wFunc=FO_DELETE 



.pFrom = FileOrigine&String$(2,0) 



.fFlags=FOF_ALLOWUNDO Or FOF_ 

SIMPLEPROGRESS 

'.lpszProgressTitle="Operazione in corso... 

"&String$(2,0) 

End With 

SHEIiminaFile=SHFileOperation(SHFileOp) 

'GESTIONE ERRORI... 

End Function 



In questa funzione, l'item pTo può essere completa- 
mente ignorato poiché non risulta necessario per 
operazioni di cancellazione. 
Naturalmente, fFlags, per maggiore sicurezza, va 
impostato con il flag FOF_ALLOWUNDO per con- 
sentire il recupero del file direttamente dal Cestino 
di Windows. 



CONCLUSIONI 

Come abbiamo potuto constatare, la libreria Shell32 
Ali ci consente di effettuare moltissime operazioni, 
più o meno semplici, che potrebbero tornarci in 
molti casi quando le normali funzioni disponibili 
non ci aiutano. 

Francesco Smelzo 



http://www.ioprogrammo.it 



Aprile 2005/ 71 ► 



VISUAL BASIC T 



XML e Visual Basic 



Tecnologia XML e database Access 



XML e Visual Basic 
da campionato! 

Completiamo l'applicazione che gestisce il calendario di un torneo a 
squadre con la presentazione dell'algoritmo e la descrizione delle 
routine che interrogano un documento e un database in formato XML 



Discussione aperta all'indirizzo 

http://forum.ioprogrammo.net/thread.php?threadid=4047&boardid=13 




Utilizza questo spazio per 
le tue annotazioni 




REQUISITI 



■ imi mii'ii'i ^m 

— Conoscenze di base sulla 
Li}J tecnologia XML, sui 
controlli MSHFlexGrid, 
WebBrowser e ADODB 




\r^3 ^3 l^il t^3 



Tempo di realizzazione 



MMM 



Questo è il secondo e ultimo appuntamento 
dedicato all'applicazione che gestisce il 
calendario di un campionato di calcio all'i- 
nel precedente appuntamento sono stati 
presentati vari aspetti funzionali, la struttura dati, le 
parti principali dell'interfaccia ed è stato fatto un 
breve cenno all'algoritmo di ottimizzazione utilizza- 
to. Si è visto che i dati principali delle squadre di cal- 
cio sono archiviati in un database Access e che la 
struttura dati di supporto all'applicazione è un do- 
cumento XML. Inoltre, sono stati presentati diversi 
argomenti correlati alla struttura dati utilizzata, qua- 
li File e alberi XML, Parser MSXML e oggetti DOM 
(Document Object Model) - il modello ad oggetti per 
manipolare un documento XML. Sono state fatte, 
anche, diverse considerazioni sul calcolo combina- 
torio e sulla notazione XPath (XML Path Language) 
usata per interrogare i documento XML. Si ricorda 
che per i nostri esemi abbiamo usato un database 
calcio.mdb contenuto nel codice allegato alla rivista, 
include una sola tabella nominata squadra ed ha i 
seguenti campi: codiceSQ, nomeSQ, calendario e 
Note. Il form principale dell'applicazione contiene 
diversi pulsanti, una MSHFlexGrid e un WebBrow- 
ser. I pulsanti abilitati, nel precedente appuntamen- 
to, sono creaalberoxml e salvaalbero. Le routine 
associate a questi due pulsanti permettono di "ini- 
zializzare" l'albero XML del campionato, di visualiz- 
zarlo nell'oggetto WebBrowser e di salvarlo in un file 
XML e nel campo calendario della tabella Squadre. 
In questo appuntamento completeremo l'applica- 











Calendario 


Carica Squadre 


Crea Albero XML | 




■l 






codiceSQ 


nomeSQ 


Gio. 1 


Gio. 2 


Gio. 3 


Gio. 4 


Gio. 5 




1 


Inter 


- ventus 


Palermo 


Milan 


Napoli 


Me:: ina 


1 2 


M ilan 


Messina 


Napoli 


Inter 


... jvenSus 


Palermo 


1 3 


Juventus 


Inter 


Messina 


Palermo 


Milan 


Napoli 


1 


Napoli 


Palermo 


Milan 


Mess ne 


Inter 


Juventus 


1 


Palermo 


Napoli 


Inter 


Juventus 


Hi i.IJ 


Milan 


G 


Messina 


Milan 


hi enl'i 


Napoli 


Palermo 


Inter 


1 











Fig. 1: Il form principale mostra i dati di un campiona- 
to a 6 squadre 



zione implementando le routine che permettono di 
generare il calendario e visualizzarlo. 



VINCOLI DA RISPETTARE 

Alla base dell'applicazione, c'è un algoritmo di otti- 
mizzazione combinatoria che considerate n squa- 
dre trova gli accoppiamenti che soddisfano determi- 
nati vincoli. In particolare per l'applicazione presen- 
tata in quest'articolo sono considerati i seguenti vin- 
coli: 

1. una squadra non può incontrare se stessa; 

2. due squadre possono incontrarsi se non si sono 
incontrate nei turni precedenti; 

3. le squadre che partecipano al campionato devo- 
no essere almeno 4 e in ogni caso non possono 
essere in numero dispari. 

Sulla base di ciò i turni di campionato sono n-1 e le 
partite per turno sono n/2. Si ricorda che il docu- 
mento XML del campionato è strutturato con i se- 
guenti i tag: <campionato>, <squadre>, <squadm>, 
<codiceSQ>, <nomeSQ> e <partite>. Campionato è il 
tag radice, squadre ha come nodi figli squadra che a 
sua volta ha come figli codiceSQ, nomeSQ e partite. 
Quest'ultimo è strutturato con i tag: <giornata> e 
<SQavversaria>. 



L'ALGORITMO 

Dopo queste premesse si descrive il codice che per- 
mette di riempire i rami partite per ogni giornata. Il 
processo di creazione dell'albero XML del campio- 
nato può essere schematizzato nel modo seguente: 

• si parte considerando l'albero XML inizializzato 
con i dati delle squadre (letti dal database); 



► 72 /Aprile 2005 



http://www.ioprogrammo.it 



XML e Visual Basic ■ T VISUAL BASIC 



• il nodo n, di quest'albero, è copiato in una varia- 
bile di comodo per essere utilizzato come ele- 
mento riempitivo in base al numero - pari o 
dispari - della giornata; 

• i primi n-1 nodi sono copiati e reinseriti nell'al- 
bero a partire dalla posizione n, poi è inserito il 
nodo di comodo. 

Dopo i passaggi precedenti, l'albero avrà (n-l)+(n- 
l)+l=2n-l nodi. 

• Sull'albero, allungato, per ogni giornata, con due 
cicli i cui estremi e step sono definiti a hoc, s'in- 
seriscono gli incontri nei nodi partite; 

• dopo i due cicli, sempre per ogni giornata, in 
partite è inserito l'elemento salvato nella varia- 
bile di comodo; 

• infine, dopo aver elaborato tutte le giornate, so- 
no eliminati gli n- 1 nodi inseriti e l'albero ritorna 
ad essere di n nodi. 



I passi precedenti sono implementati con la proce- 
dura^^ BSfl5!^SMB 3> invocata con il pulsante 
Genera del form principale. La GeneraCalendario 
dopo aver creato il calendario visualizza il contenu- 
to dei nodi partite nella hJ&ffifflsSSJ- n calendario 



Si fa notare che n contiene il numero di squadre par- 
tecipanti al campionato e che SQComodo è di un ti- 
po che raggruppa un nome e un codice. La variabile 
n è impostata quando si leggono i nomi delle squa- 
dre dal database. La procedura GeneraCalendario è 
la seguente. 

^ Private Sub GeneraCalendario_Click() 

If n = Then 

MsgBox "Prima Caricare le squadre", vbCritical 

Exit Sub 

End If 



'bisogna mischiare i nodi 



Dim comlist As IXMLDOMNodeList 



Dim num As Integer 



Set comlist = xmldocument.documentElement 
.selectNodes("//squadre/*") 



num = comlist. length 



SQComodo. codice 



comlist. Item(num - 1) 
.childNodes.Item(Q).Text 



SQComodo. nome = comlist. Item( 

num - l).childl\lodes.Item(l).Text 



1 



aggiunginodi 



n2 = (n - 1) / 2 



For turno = 1 To n 



completo del campionato, invece, si può ricavare 
con il form FrmSelezione, non presentato nell'arti- 
colo ma inserito nel progetto fornito con il CD alle- 
gato alla rivista. Form FrmSelezione si avvia con il 
pulsante Interroga del form principale. 

CREARE IL CALENDARIO 

In questo paragrafo è introdotta la procedura 
GeneraCalendario - che crea il calendario XML - e le 
procedure correlate, vale a dire: 

• Aggiunginodi e Cancellanodi, che permettono di 
aggiungere ed eliminare dei nodi dall'albero 
XML; 

• Inseriscilncontro e InseriscilncontroTemp, che 
consentono d'inserire gli avversari nei rami par- 
tite. 

In particolare la InseriscilncontroTemp è utilizzata 
per inserire la squadra di posizione n, cioè quella 
salvata nella variabile di comodo. Questa variabile è 
nominata SQComodo ed insieme con altri elementi 
è dichiarata in un modulo come mostrato di seguito: 

Public n As Integer 

Public xmldocument As DOMDocument 

Public Type Squadra 

nome As String 

codice As Integer 

End Type 

Public SQComodo As Squadra 



For pos = turno + 1 To turno + n2 Step 2 

Inseriscilncontro pos, turno + turno - pos + n, turno 



Next pos 



For pos = turno + 2 To turno + n2 Step 2 

Inseriscilncontro turno + turno - pos + n, pos, turno 
Next pos 



Dim codice As Integer 



Dim nome As String 



codice = SQComodo.codice 



nome = SQComodo. nome 



If ((turno Mod 2) <> 0) Then 



Inseriscilncontrotemp turno, 1 



Else 



Inseriscilncontrotemp turno, 2 



End If 



Next turno 



Cancellanodi 



i Caricagriglia 



Salva. Enabled = True 



'abilita il pulsante salva 



GeneraCalendario. Enabled = False 



'disabilita il pulsante 



End Sub 

Nella GeneraCalendario dopo aver impostato l'ulti- 
mo nodo nella variabile SQComodo e decrementato 
n di un'unità (dato che diminuiscono le squadre) è 
invocata la nroceduragjBg ffl jj ^ fffi flche allunga l'al- 
bero. 



Private Sub AggiungiNodiQ 





GLOSSARIO 



SMART 
DOCUMENT 

Gli Smart Document 
sono strumenti di 
Office 2003 
particolarmente utili 
per la creazione di 
soluzioni che si 
sviluppano secondo un 
determinato processo. 
Gli Smart Document 
possono essere 
implementati, con vari 
linguaggi (Visual Basic 
6, C#, C++ e VB Net) sia 
in tecnologia COM che 
.NET e possono 
interagire con database 
Access e SqlServer. Gli 
Smart Document 
possono essere 
sviluppati per una rete 
locale o geografica e 
quindi usare Web 
Service e Siti Web 
basati su SharePoint 
Portai Server 2003. 
Gli Smart Document 
sono sviluppati con 
Smart Document SDK. 
Sarebbe interessante 
sviluppare uno Smart 
Document per la 
gestione dei calendari! 



Dim figlio As IXMLDOMEIement 



http://www.ioprogrammo.it 



Aprile 2005/ 73 ► 



VISUAL BASIC T 



XML e Visual Basic 




Dim Qpadre As IXMLDOMEIement 



com.removeChild comlist.Item(i) 



Dim i As Integer 



For i 



1 To n 



Set Qpadre = xmldocument.createNode( 
NODE_ELEMENT, "squadra", "") 

xmldocument.selectSinglel\lode(radice 
+ "/squadre").appendChild Qpadre 

Set figlio = xmldocument.createNode( 
"element", "codiceSQ", "") 



Qpadre.appendChild figlio 



Set figlio = xmldocument.createNode( 

"element", "nomeSQ", "") 



Qpadre.appendChild figlio 



Set figlio = xmldocument.createNode( 
"element", "partite", "") 



Qpadre.appendChild figlio 



Set figlio = Nothing 



Next i 



Dim comlist As IXMLDOMNodeList 



Set comlist = xmldocument.documentElement 
.selectNodes("//squadre/*") 



For i 



1 To n 



comlist. Item(i + n - l).childNodes.Item(0).Text = _ 

comlist. Item(i - l).childNodes.Item(0).Text 
comlist. Item(i + n - l).childNodes.Item(l).Text = _ 

comlist. Item(i - l).childNodes.Item(l).Text 
Next i 
comlist. Item(n + n).childl\lodes.Item(0).Text = 

SQComodo.codice 

comlist. Item(n + n).childNodes.Item(l).Text = 

SQComodo.nome 
End Sub 

L'AggiungiNodi clona n nodi (con n = numero squa- 
dre-I) utilizzando due cicli. Con il primo inserisce n 
nodi squadra ed i relativi nodi figli {codiceSQ, no- 
meSQ e partite); col secondo, invece, copia i valori 
dei primi n nodi in quelli inseriti. Dopo i due cicli, 
infine, si copiano i valori della variabile SQComodo 
nell'ultima posizione dell'albero. Si fa notare che la 
numerazione dei nodi nella collezione comlist inizia 
da zero. Per esempio quando il numero di squadre 
n=6, dopo queste operazioni l'albero XML ha 11 no- 
di vale a dire 2 volte i primi 5 nodi più il nodo SQCo- 
modo. Dato che i nodi aggiunti con la procedura 
precedente sono soltanto di supporto, alla fase di 
creazione del calendario, devono essere eliminati al- 
la fine del processo. Questo si fa attraverso la se- 
guente procedura. 

Private Sub CancellanodiQ 

Dim com As IXMLDOMNode 

Dim comlist As IXMLDOMNodeList 

Set com = xmldocument.documentElement 

.selectSingleNode("//squadre") 

Set comlist = xmldocument.documentElement 

.selectNodes("//squadre/*") 



Next 



End Sub 

Nella Cancellanodi prima è valutato il numero 
complessivo di nodi dell'albero - utilizzando la 
proprietà length della collezione di nodi - e poi, in 
un ciclo, sono eliminati i nodi al disotto del nodo n, 
tranne l'ultimo. 

Si noti che -2 è necessario dato che i nodi sono 
numerati a partire da zero e l'ultimo nodo dell'al- 
bero non deve essere cancellato (dato che contiene 
i dati della squadra di "comodo"). 
Le procedure Inseriscilncontro e Inseriscilncontro- 
Temp sono le seguenti. 

Public Sub InserisciIncontro(posl As Integer, pos2 

As Integer, _ giornata As Integer) 

Dim comlist As IXMLDOMNodeList 

Dim elei As Squadra 

Dim ele2 As Squadra 



Set comlist ■■ 



xmldocument.documentElement 

.selectNodes("//squadre/*") 

elel.codice = comlist.Item(posl).childNodes.Item(Q).Text 
elei. nome = comlist. Item(posl).childNodes.Item(l).Text 
ele2.codice = comlist.Item(pos2).childNodes.Item(0).Text 
ele2.nome = comlist. Item(pos2).childNodes.Item(l).Text 

Appendlncontro elei, ele2, giornata 

End Sub 

La Inseriscilncontro è invocata dalla GenemCalenda- 
rio quando è necessario inserire un incontro tra due 
squadre, per questo i parametri della procedura 
sono due posizioni (posi e pos2) e il turno. In base a 
questi parametri dall'albero vengono ricavati il no- 
me e il codice delle squadre e inseriti, per il turno 
specificato, una nel ramo partite dell'altra. Per inse- 
rire gli incontri della squadra di comodo, invece, è 
utilizzata la seguente. 

Public Sub InserisciIncontrotemp(giornata As Integer, 
qualepara As Integer) 

Dim comlist As IXMLDOMNodeList 

Dim pos As Integer 

pos = giornata 

Dim elei As Squadra 

Dim ele2 As Squadra 

Set comlist = xmldocument.documentElement 
.selectNodes("//squadre/*") 



If qualepara = 1 Then 



elei = SQComodo 



ele2.codice = comlist.Item(pos).childNodes.Item(Q).Text 
ele2.nome = comlist. Item(pos).childNodes.Item(l).Text 



Else 



ele2 = SQComodo 



For i = n To comlist. length - 2 



elel.codice = comlist.Item(pos).childNodes.Item(Q).Text 
elei. nome = comlist. Item(pos).childNodes.Item(l).Text 
End If 



► 74 /Aprile 2005 



http://www.ioprogrammo.it 



XML e Visual Basic ■ T SISTEMA 



Appendlncontro elei, ele2, giornata 

End Sub 

La InseriscilncontriTemp è invocata dalla GeneraCa- 
lendario in base al tipo di giornata, dispari o pari; 
questo giustifica i tipi di parametri. Le due procedu- 
re precedenti per aggiornare i nodi utilizzano l'Ap- 
pendlncontri, mostrata in seguito. 

Public Sub AppendIncontro(elel As Squadra, _ 

ele2 As Squadra, giornata As Integer) 

Dim com As IXMLDOMEIement 

Set com = xmldocument.createNode(NODE_ELEMENT, 

"giornata", "") 

com.Text = CStr(giornata) 

xmldocument.selectSingleNode("campionato 
/squadre/squadra [ codiceSQ = " & CStr(elel. codice) 

+ " ]/partite").appendChild com 

Set com = xmldocument.createNode(NODE_ELEMENT, 

"SQavversaria", "") 



com.Text = CStr(ele2.nome) 



xmldocument.selectSingleNode("campionato 

/squadre/squadra [ codiceSQ = " & CStr(elel. codice) 
+ " ]/partite").appendChild com 

Set com = xmldocument.createNode(NODE_ELEMENT, 
"giornata", "") 



com.Text = CStr(giornata) 



xmldocument.selectSingleNode("campionato 

/squadre/squadra [ codiceSQ = " & CStr(ele2. codice) 
+ " ]/partite").appendChild com 

Set com = xmldocument.createNode(NODE_ELEMENT, 
"SQavversaria", "") 



com.Text = CStr(elel.nome) 



xmldocument.selectSingleNode("campionato 
/squadre/squadra [ codiceSQ = " & CStr(ele2. codice) 

+ " ] /partite").appendChild com 

End Sub 

Nel paragrafo successivo si descrive la procedura 
che carica gli avversari delle squadre nella MSFlex- 
Grid della maschera principale, cioè la procedura 
CaricaGriglia invocata dalla GeneraCalendario dopo 
aver cancellato i nodi di supporto. 



VISUALIZZARE LE 
PARTITE IN UNA GRIGLIA 

In questo paragrafo è descritta la procedura Cari- 
caGriglia che popola la MSHFlexGrid con i dati del 
documento XML che contiene il calendario degli 
incontri. Si presuppone che il documento XML sia 
già caricato, altrimenti si può fare seguendo le 
indicazioni date nel precedente articolo. 
La CaricaGriglia legge i dati da un documento 
XML nominato xmldocument e l'inserisce nella 
MSHFlexGridl. Questo viene fatto secondo i se- 
guenti passi: 



1 . si valuta il numero di nodi squadra presenti nel- 
l'albero; 

2. in base al numero di squadre s'impostano il 
numero di colonne e di righe della griglia; 

3. con due ciclo, per ogni squadra e per ogni gior- 
nata, s'inseriscono i dati nella griglia; 

4. s'imposta il numero di colonne fisse. 

La procedura è la seguente. 

Sub caricagrigliaQ 

Dim Qlist As IXMLDOMNodeList 

Dim Plist As IXMLDOMNodeList 



Dim i, j As Integer 



Dim Qnum As Integer 



Dim Pnum As Integer 



Dim colonna As Integer 



Set Qlist = xmldocument. documentElement.selectNodes( 
"//squadre/*") 



Qnum = Qlist. length 



MSHFlexGridl.CoIs = Me. MSHFlexGrid l.CoIs + Qnum - 1 



'numero di righe già impostate 



For i = 1 To Qnum 



colonna = 1 



If i <= Qnum - 1 Then 



MSHFIexGridl.TextMatrix(Q, i + 1) 
End If 



"Gio. " + CStr(i) 



For j = 2 To (Qnum - 1) * 2 Step 2 



colonna = colonna + 1 



MSHFIexGridl.TextMatrix(i, colonna) = Qlist. Item( 
i - l).childNodes.Item(2).childNodes.Item(j - l).Text 



Next 



Next 



MSHFlexGridl. FixedCoIs 



End Sub 

Si noti che è utilizzato il metodo TextMatrix che con- 
sente di selezionare e caricare una singola cella della 
griglia. Come caricare in una listbox i dati sugli 
incontri contenuti nel database Calcio. 



CONCLUSIONI 

Gli algoritmi proposti in questa miniserie di due 
articoli sono solo una delle tantissime implemen- 
tazioni a cui si presta un problema di calcolo com- 
binatorio come quello esposto. 
Sul forum di ioProgrammo trovate tante e fanta- 
siose soluzioni al problema, alcune delle quali 
molto matematiche. 

È divertente notare come l'approccio alla pro- 
grammazione coinvolce anche lo stile personale 
nella risoluzione dei problemi. Qui abbiamo pre- 
ferito usare XML perché ci sembrava particolar- 
mente pratico, ma se avete altre soluzioni da pro- 
porre, il forum vi attende. 

Massimo Autiero 





GLOSSARIO 



XPATH 

E SELEZIONE 

MODI CON [] 

La notazione XPath 
(XML Path Language) è 
usata per interrogare 
un documento XML, 
essa è supportato dal 
Parser MSXML dentro 
le XSLT e con gli 
elementi selectNodes e 
selectSingleNode. 
L'XPath è una 
notazione dichiarativa 
per questo con essa si 
descrivono delle 
relazioni gerarchiche 
tra nodi. Per esempio 
con la seguente 
espressione 
"campionatolsquadre/s 
quadra [ codiceSQ = " _ 
&CStr(2)+ "] /partite" 
è selezionato il nodo 
partite della squadra 
con codiceSQ=2 



http://www.ioprogrammo.it 



Aprile 2005/ 75 ► 



VISUAL BASIC T 



XML e Visual Basic 





ADODB SAVE 

FORMATO XML 

E LOADXML 

Il metodo save di un 

oggetto Recordset 

permette di salvare il 

suo contenuto in un 

oggetto o in un file. La 

sintassi è la seguente: 

recordset Save 

Destinazione, 

PersistFormat. 

Destinazione è il nome 

di un file o di un 

oggetto, PersistFormat 

specifica in che 

formato deve essere 

salvato il Recordset. 

/possibili valori sono: 

adPersistADTG e 

adPersistXML 

Il primo è il formato 

predefinito cioè il 

formato binario; 

AdPersistXML, invece, 

è il formato XML. 

Il documento XML 

prodotto con la save 

presenta vari elementi 

quello che bisogna 

usare per recuperare i 

dati del campo 

calendario è 

"llrs:datalz:rowl@calen 

dar io ". 

Invece per recuperare 

la struttura di un 

documento XML da 

una stringa che 

contiene dati in 

formato XML si può 

utilizzare il metodo 

IoadXML dell'oggetto 

DomDocument. 



CARICARE UHI DOCUMENTO XML 
CON INTERNET EXPLORER 

Come caricare in una listbox i dati sugli incontri di calcio contenuti nel 
database Calcio.mdb 

risultato della query e l'altro per ricostruire la 
struttura dell'albero XML con la IoadXML. Si 
ricorda che i dati sugli incontri sono contenuti 
nel campo calendario riempito quando si clicca 
il pulsante Salva del form principale. 




ONel progetto includere un riferimento a 
MSXML4.dll (Microsoft XML, v4.0) e a 
Microsoft Activex Data Object (ADO). Sul form, 
invece, inserire almeno un textbox - nominato 
txtcodiceSQ, un pulsante - nominato Caricai - e 
un listbox. 



Private Sub Caricacal_Click() 



If Not IsNumeric(txtcodiceSQ) Then 



MsgBox "Specificare correttamente il " & 
"codice della squadra", vbCritical, 
Exit Sub 



'Errore" 



End If 



Dim xmldocument As DOMDocument 



Dim com As String 



Set xmldocument = trovacal("select calendario" & 

" from squadra where codiceSQ=" + txtcodiceSQ) 
Dim xmldocument2 As DOMDocument 



Set xmldocument2 = New DOMDocument 



On Error Resumé Next 



com = xmldocument. selectSingleNode . 



(7/rs:data/z:row/@calendario").Text 
If com = "" Then 
Err.Clear 



MsgBox "Codice squadra errato o" 

& " database vuoto", vbCritical, "Errore" 



Exit Sub 



End If 

xmldocument2. IoadXML com 
Dim comlist As IXMLDOMNodeList 



Listi. Addltem "Creato Albero con IoadXML" 



Listi. Addltem "Squadra: " +xmldocument2 

.documentElement.childl\lodes.Item(l).Text 



Set comlist = xmldocument2. 

documentElement.selectNodes("//partite/*") 
Listi. Addltem "Giornata - avversaria" 



For i = To (comlist.length - 1) Step 2 



Listi. Addltem comlist. Item(i).Text & " - " 

+ comlist. Item(i + l).Text 



Next 
End Sub 



HNel pulsante devono essere inserite le 
istruzioni che leggono il codice della squa- 
dra da txtcodiceSQ, inviano la query al 
database e caricano i dati ricevuti in un docu- 
mento XML. La procedura del pulsante è la se- 
guente. Si fa notare che nella Caricacal si usano 
due oggetti DOMDocument, uno per ricevere il 



Public Function trova cal(By Val strQuery As String) 

As DOMDocument 

Dim xmldocument As DOMDocument 



Set xmldocument = New DOMDocument 



Dim objConn As ADODB.Connection 



Dim rs As ADODB. Recordset 



Set objConn = New ADODB.Connection 
Set rs = New ADODB. Recordset 



objConn. Open "Provider=Microsoft.Jet.OLEDB.4.0;' 
& "Data Source=" + App.Path + "\calcio.mdb", "", 



rs.Open strQuery, objConn 

rs.Save xmldocument, adPersistXML 

Set trovacal = xmldocument 



Set xmldocument = Nothing 



rs.Close 



Set rs = Nothing 

objConn. Close 

Set objConn = Nothing 



End Function 



La Caricacal _Click per eseguire la query 
utilizza la funzione trovacal. Questa riceve 
una query select e restituisce un documento 
XML creato con il metodo Save del recordset. 



Dim strfile As String 



strfile = App.Path + "\" + "calendario" _ 
& xmldocument2.documentElement.childNodes. _ 
Item(l).Text + ".xml" 



xmldocument2.Save (strfile) 



□ Infine per salvare i dati degli avversari in 
un file XML, alla Caricacal si devono 
aggiungere le seguenti istruzioni 



L:\Documents and bettings\job\ )esktop\Prossimi Urti Vai 


- <squadra> 

<codiceSQ>3</codiceSQ> 
<nomeSQ>Juventus</nomeSQ> 




±J 


pWffl— 




















Nonne file | 




carica 












Codice | 3 ;" Carie a Avversari"";! 








Giornata 1 | Incontri giornata 


Tutti 


I f 




Creato Àlbero con IoadXML 
Squadra: Juventus 
Giornata ■ avversaria 

1 - Inter 

2 - Messina 

3 - Palermo 

4 - Milan 

5 - Napoli 



Si noti che il nome del file XML è del tipo 
"calendario" + "nome squadre corrente", 

dove il nome della squadra è recuperato 

dall'albero xmldocument2. 



► 76 /Aprile 2005 



http://www.ioprogrammo.it 



Spam addio ■ T BACKSTAGE 



Il teorema di Bayes per difenderci dalle email indesiderate 

Filtri bayesiani contro 
la posta spazzatura 

In questo articolo parleremo dei principali sistemi di protezione, 
e implementeremo un filtro bayesiano creando un dizionario 
personalizzato, eseguendo alcuni calcoli statistici necessari 



Pare che il traffico generato dalla posta 
spazzatura costituisca, insieme a quel- 
lo prodotto dai crawler dei motori di 
ricerca, la maggior parte di quello prodotto 
sull'intera rete. In altre parole, se non ci fosse 
posta spazzatura e l'indicizzazione dei moto- 
ri di ricerca funzionasse con modalità diver- 
se, Internet sarebbe molto più veloce e 
potrebbe supportare molti più utenti con lo 
stesso hardware. Per proteggersi dai messaggi 
indesiderati sono nati diversi strumenti soft- 
ware. Le tecniche maggiormente utilizzate 
per implementare dei sistemi antispam pos- 
sono riassumersi nelle seguenti categorie: 

• Ricerca di elementi chiave - Il testo del 
messaggio viene analizzato e per ogni 
caratteristica sospetta viene assegnato un 
punteggio. Ad esempio, un testo solo 
HTML, colori forti, intestazioni di posta 
particolari, l'uso di termini riconducibili a 
posta spazzatura, sono tutti elementi che 
alzano il punteggio spazzatura del mes- 
saggio. Se questo supera un certo valore, il 
software segnala il messaggio come spaz- 
zatura. 

• white/black list - In questo caso l'utente 
costruisce, in modi più o meno automati- 
ci, una lista di mittenti conosciuti ed 
accreditati e/o una lista di mittenti non 
accreditati. Il filtro di posta sui messaggi 
in arrivo farà passare solo i messaggi i cui 
mittenti sono in white list, mentre cancel- 
lerà quelli in black list. Quelli non presen- 
ti in nessuna delle due liste potrebbero 
essere presentati all'utente per una scelta 
manuale; 

• filtri statistici - Entrambi gli approcci 
sopra illustrati hanno prò e contro. Ad 



esempio, il primo produce risultati vicini 
al 70%-80% ma rende quasi impossibile 
riconoscere il restante 30%-20% di posta. 
Restringendo i parametri di filtro si rischia 
di ottenere falsi positivi. Ovvero messaggi 
erroneamente indicati come posta spaz- 
zatura. L'approccio a white/black list in- 
vece presenta lo svantaggio di dover gesti- 
re manualmente l'elenco dei mittenti. Per 
ovviare a questi problemi è possibile uti- 
lizzare i filtri statistici. Questi sono noti 
anche come filtri bayesiani, dal nome del- 
l'invetore della teoria che sta alla loro ba- 
se, Thomas Bayes. 

I filtri bayesiani eseguono un'analisi dei mes- 
saggi che l'utente indica essere posta spazza- 
tura, e costruiscono un dizionario di termini 
"sospetti". Poi analizzano la posta accettata, e 
costruiscono un dizionario di termini "legitti- 
mi". Sulla base di questi dizionari, sono in 
grado di identificare quali messaggi potreb- 
bero essere spazzatura o meno. 
Solitamente questa analisi viene svolta all'i- 
nizio e prende il nome di "allenamento". In 
sostanza, appena dopo aver installato il filtro 
nel nostro programma di posta, è necessario 
passare qualche giorno indicando al sistema 
quale dei messaggi ricevuti è buono e quale 
invece è posta spazzatura. Quando la fase di 
allenamento viene conclusa, il sistema filtra 
autonomamente i messaggi, marcandoli co- 
me spazzatura o posta accettata. Il vantaggio 
dei filtri statistici è che la logica è basata su 
un teorema statistico comprovato. 

II software non azzarda valutazioni la cui 
logica potrebbe essere opinabile. Inoltre il fil- 
tro funziona sulla base della propria specifica 
fase di allenamento. Sulla base cioè della spe- 
cifica posta spazzatura e posta legittima che 
l'utente riceve. In questo modo l'analisi è 




□ CD □ WEB 

ian-0.1.tgz 




I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



n 




REQUISITI 



WMMUUUMUJkBim 
r^a Linguaggio Java 




Tempo di realizzazione 



(s\ (.y\ 



http://www.ioprogrammo.it 



Aprile 2005/ 77 ► 



BACKSTAGE T 



Spam addio 




CLIENT 
DI POSTA 

Alcuni client di posta 

che implementano 

direttamente un filtro 

bayesiano contro la 

posta spazzatura sono 

Mail di Apple, il 

programma di posta 

elettronica di Mac OSX 

http://www.apple.com/it/ 

oppure Thunderbird, il 

client di posta del 

progetto Mozilla 

http://www.mozilla.org/ 

projects/thunderbird/ 



focalizzata e specifica. Con questi filtri si può 
ottenere un'approssimazione vicina al 99%. 



IMPLEMENTARE 
Ul\l DIZIONARIO 

Il primo passo da fare per implementare un 
filtro bayesiano è quello di costruire un dizio- 
nario. Poi dovranno essere eseguiti alcuni cal- 
coli statistici, ma niente di particolarmente 
complesso. Il dizionario contiene una serie di 
parole, con il numero di occorrenze delle 
stesse nelle mail passate per la fase di allena- 
mento. Nei nostri esempi questa fase verrà 
simulata da due file mbox, uno che contiene 
una serie di messaggi spazzatura. L'altro con- 
tiene posta legittima. 

La prima fase è dunque quella di produrre 
una classe che dato un file mbox ne produca 
il dizionario delle parole con le relative occor- 
renze. 
Un esempio di contenuto del dizionario è: 



Dizionario posta Rifiutata; 



Access=1.0 


account=9.0 


acquisition = 5.0 




commercial = 3.0 


communicable=0.0 


communicate=1.0 


Company=17.0 




lots=1.0 


Lou = 5.0 


love=5.0 


Low=3.0 


Ltd. = 2.0 



Avremo chiaramente bisogno di un diziona- 
rio delle parole corrette e uno delle parole 
spazzatura. 

COSTRUZIONE 
DEL FILTRO 

Una volta in possesso di dizionari ben compi- 
lati, è possibile creare il filtro di posta. Quello 
che verrà costruito nelle pagine seguenti è 
basilare, ed opera su un singolo messaggio di 
posta, passato come stringa o caricato da un 
file. 

Il filtro è implementato con una singola clas- 
se FiltroBay esiano, dichiarata come segue: 



Crea un nuovo filtro, utilizzando i dizionari di posta 



* accettata e rifiutata indicati 



@param posta Accettata 



@param postaRifiutata 



V 



public FiltroBayesiano( Dizionario postaAccettata, 
Dizionario postaRifiutata ) 



±_ 



this. postaAccettata = postaAccettata; 



this.postaRifiutata = postaRifiutata; 



> 



il codice prevede un singolo costruttore che si 
aspetta i due dizionari di riferimento. Il meto- 
do che esegue il filtro del contenuto di un file 
non fa altro che caricare in memoria il file: 

public float filtra( File file ) throws IOException 

{ 

FileReader fr = new FileReader(file); 

char[] buffer = new char[ (int) file.length() ]; 

fr.read( buffer ); 



fr.close(); 



return 



5tring(buffer) 



> 



il file viene caricato in un unico blocco di 
caratteri, memorizzati in un array di char. Da 
questo viene costruita una stringa, che viene 
passata al metodo filtra(String). Questo con- 
tiene la logica di valutazione del messaggio, 
che sostanzialmente è composta da tre pas- 
saggi: 

1. estrazione di tutte le parole presenti nel 
messaggio, in modo similare a quanto 
fatto per la costruzione dei dizionari e cal- 
colo delle probabilità dei singoli token; 

2. estrazione delle parole che hanno proba- 
bilità più lontana dal punto medio, identi- 
ficato da una probabilità dello 0.5. ; 

3. calcolo della probabilità combinata di 
tutti i termini, che produce la probabilità 
che il messaggio sia posta indesiderata. 

il codice sorgente è il seguente: 



public class FiltroBayesiano 



{ 



Dizionario postaAccettata; 



public float filtra( String messaggio ) •- 

{ 

Map tokenProb = new HashMapQ; 



► 78 /Aprile 2005 



http://www.ioprogrammo.it 



Spam addio ■ T BACKSTAGE 



DEFINZIONE DELLA CLASSE 



public class Dizionario 
{ 



public final static String TOKENS = "!#* \t\n,:"; 
Map dizionario = new HashMapQ; 



String filename; 



* Crea un dizionario di termini e loro occorrenze 



* @param filename file che contiene la casella 

da analizzare 



*/ 



public Dizionario( String filename) 

{ 
this. filename = filename; 



} 



DPer prima cosa viene definita la classe 
Dizionario, che dispone di tre attributi: 
una costante che indica quali sono i 
separatori di parola, una Map che conterrà le 
parole e le occorrenze ed una stringa per 
ospitare il nome del file da caricare. La classe 
ha un costruttore che permette di specificare 
il nome del file da leggere 

LETTURA DEL FILE 



public void importaQ throws IOException 
{ 



FileReader fr = nuli; 



try 



fr = new FileReader( filename ); 
BufferedReader br = new BufferedReader( fr ); 



while( true ) 



{ 



String line = br.readLineQ; 



if (line= = null) {break;} 

StringTokenizer st = new 
StringTokenizer( line, TOKENS ); 



while( st.hasMoreTokensQ ) 



{ increment( st.nextTokenQ );} 



} 



_ì 

finally 

{ 



if (fr == nuli) {fr.closeQ; 



} 



System. out.println("Importata la casella " 

+ filename + " per un totale di " + 

dizionario. size() + " token"); 

// System.out.println( dizionario ); 



} 



HLa seconda fase prevede la lettura del 
file di testo, utilizzando un oggetto 
FileReader associato ad un BufferedReader. In 
questo modo viene letta una riga alla volta e 
spezzata in token attraverso un oggetto 
StringTokenizer. Questo viene costruito con la 
costante TOKENS definita al passo 
precedente. In questo modo viene considerata 
una parola unica tutto quanto non separato 
dai caratteri sopra indicati. Per ciascuna pa- 
rola così ottenuta viene chiamato il metodo 
incremento, che si occupa di aumentare il 
conteggio di questa parola, se non esiste 



INCREMENTO DEL CONTATORE 



void increment( String token ) 



{ 



Float count = (Float)dizionario.get(token); 
if (count == nuli) 



count = new Float(l); 



else 
{ 



count = new Float( count.floatValueQ + 1 ); 



} 



dizionario.put( token, count ); 



> 



Il metodo incremento verifica se nel 
dizionario è già presente la parola. In 
questo caso ne ottiene il numero di occorren- 
ze, che aumenta di uno, per poi reinserire i 
dati aggiornati nel dizionario. Nel caso la 
parola non esista, viene inserita nel diziona- 
rio con contatore a 1 

FUNZIONI DI SUPPORTO 



float get( String token ) 

{ 

Float value = (Float)dizionario.get(token); 



if (value == nuli) 



{return O.Of;} 



else 



return value.floatValueQ; 



±_ 



} 



□ La classe viene poi integrata con due 
funzioni aggiuntive, che permettono di 
investigare i dati del dizionario da un'altra 
classe. Il metodo get() ritorna il numero di 
occorrenze di una parola passata come para- 
metro. Se questa non esiste nel dizionario 
viene ritornato O.Of. Il dato viene restituito 
come tipo primitivo float per agevolare le 
operazioni successive 

NUMERO DI PAROLE NEL DIZIONARIO 



int size() {return dizionario. size();> 



L'altro metodo presente è sizeQ, che ri- 
torna il numero di parole nel dizionario 



COSTRUIAMO IL DIZIONARIO 



Dizionario dizionarioJunk = new 

Dizionario("junk.mbox"); 



dizionarioJunk. importaQ; 



Dizionario dizionarioNormale = new 

Dizionario("normale.mbox"); 



dizionarioNormale. importa(); 



HA questo punto è possibile costruire i 
due dizionari necessari all'operatività di 
un filtro bayesiano. Il codice seguente crea i 
due dizionari dizionarioJunk e dizionarioNor- 
male caricando i due file junk.mbox e norma- 
le.mbox, costruiti estraendo caselle di poste 
create da un programma di posta elettronica. 




CREAZIONE 
FILE MBOX 

Il programma di 
esempio cerca i file 
junk.mbox e 
normale.mbox dalla 
directory corrente. 
Questi file dovranno 
contenere un certo 
numero di messaggi 
spazzatura e legittimi, 
per la fase di 
allenamento del filtro. 



CREAZIONE 
DEI MESSAGGI 
DI PROVA 

I messaggi da 
analizzare sono 
contenuti nei file 
bad.txt, bad1.txt, 
good.txt e good1.txt. si 
noti che possono 
includere le 
intestazioni di posta o 
meno. I primi due sono 
messaggi spazzatura, 
gli altri due messaggi 
legittimi. 



http://www.ioprogrammo.it 



Aprile 2005/ 79 ► 



BACKSTAGE T ■ Spam addio 





StringTokenizer st = new StringTokenizer( 

messaggio, Dizionario. TOKENS ); 

while( st.hasMoreTokens() ) 
J 



String token = st.nextToken(); 



tokenProb.put( token, calcolaProbabilità(token)); 



System.out.println( tokenProb ); 



ALL'ENNESIMA 
POTENZA 

Quanto mostrato in 

questo articolo è 

basilare e tratta 

direttamente con i 

meccanismi statistici di 

base per implementare 

i teoremi di Bayes. Su 

Sourceforge.net è però 

presente un progetto 

che integra ed estende 

queste funzionalità, 

una libreria di 

classificazione di 

termini che 

implementa anche un 

filtro bayesiano. 

È disponibile 

all'indirizzo 

http://classifier4j.sourcefo 

rge.net/ 



float[] pb = estraiProbabilità( tokenProb ); 



return probabilitàCombinata( pb ); 



> 



il primo passo viene espletato tramite l'ogget- 
to di tipo StringTokenizer. L'approccio è simi- 
le alla classe Dizionario ma nella mappa, per 
ogni parola, non è presente il numero di 
occorre nze, ma la probabilit à calcolata con il 
metodo WfKMMi TlfìMlfTW Q. Questo metodo 
mette in relazione le occorrenze della parola 
nei dizionari di posta accettata e rifiutata, 
calcolando la probabilità che la mail che con- 
tiene questa parola sia indesiderata. Se una 
parola non è presente nei dizionari assume 
un valore di 0.4: 



» Float calcolaProbabilità( String token ) 
{ 



float result = 0.4f; 



float g = postaAccettata.get(token) * 2; 



float b = postaRifiutata.get(token); 



if( !((g + b) < 5)) 



_±_ 



float tempi = b / postaRifiutata.sizeQ; 



tempi = Math.min( tempi, 1 ); 



float temp2 = g / postaAccettata.sizeQ; 



SUL WEB 



Una fonte d'informa- 



zioni preziosa per cono- 
scere maggiori dettagli 
sui filtri bayesiani, tut- 
ta la teoria col legata, e 
molti altri argomenti, è 
l'enciclopedia gratuita 
Wikipedia - the free 
encyclopedia. 
Un enorme wiki su 
qualsiasi argomento, 
dispone di moltissimi 
articoli. 
I filtri bayesiani sono 
ottenibili all'indirizzo 
http://en.wikipedia.org/ 
wiki/Bayesian filtering 



temp2 = Math.min( temp2, 1 ); 



float temp = tempi / (templ+temp2); 



result = Math.min( 0.99f, temp ); 



result = Math.max( O.lf, result ); 



±_ 



return new Float(result); 



> 



la formula utilizzata non è altro che quella 
descritta nella documentazione di Graham (si 
veda il box "Un piano per la posta indesidera- 
ta"). 



CALCOLI STATISTICI 

Una volta ottenuto il dizionario dei token del 
messaggio da valutare, vengono considerati i 



15 elementi con maggior discostamento dal 
punto medio 0.5. Si noti che il discostamento 
deve considerare il segno. 
Ad esempio, un valore 0.8 si discosta di 0.3 dal 
punto medio, mentre un valore 0.3 si discosta 
di 0.2: 

| 0.8 - 0.5 | = 0.3 

| 0.3 - 0.5 | = 0.2 

per ottenere l'elenco dei token ordinati per 
discostamento, viene costruita una mappa 
ordinata. Nella mappa la chiave è il punteg- 
gio, mentre il valore è la probabilità. Da que- 
sta mappa vengono estratti i primi quindici 
elementi e ritornati sottoforma di array di 
float: 

float[] estraiProbabilità( Map dizionario ) 

{ 

final int size = 15; 

float[] pb = new float[ size ]; 

//crea una mappa con le probabilità ed i punteggi 
//relativi cioè la distanza dal valore medio 



Map punteggi = new TreeMapQ; 



for( Iterator iter = dizionario.keySet().iterator(); 



iter.hasNextQ; ) 



String key = (String)iter.nextQ; 



Float currentObject = (Float)dizionario.get(key); 

float current = currentObject.floatValueQ; 

float punteggio = Math.abs( current - 0.5f ); 



punteggi. put( new Float( punteggio ), 
currentObject ); 



//la mappa è ordinata per chiave, dunque estraendo i 
//primi 15 elemeni si anno le probabilità più lontane 
//dal valore medio 



int i 



for( Iterator iter = punteggi. keySet().iterator(); 
iter.hasNextQ; ) 



_ì_ 



Float key = (Float)iter.nextQ; 



Float currentObject = (Float)punteggi.get(key); 



pb[ i++ ] = currentObject.floatValueQ; 



if (i>=size) 



_±_ 



break; 



return pb; 



► 80 /Aprile 2005 



http://www.ioprogrammo.it 



Spam addio ■ T BACKSTAGE 



una volta in possesso di questo array di pro- 
babilità, è possibile calcolare la probabilità 
combinata. Cioè la probabilità che tutti i casi 
si verifichino. 
La formula relativa è: 

abc 

abc + (l-a)(l-b)l-c) 

dove a, b e e sono valori di probabilità. 
Ovviamente la formula si espande fino a con- 
templare tutte e quindici le probabilità 
estratte al passo precedente. La probabilità 
combinata è implementata nel metodo se- 
guente: 

float probabilitàCombinata( float[] pb ) 

{ 

float result = 0; 

//calcola il prodotto delle probabilità 

float prodotto = pb[0]; 

for( int i=l; i<pb.length; i++ ) 

_i 

prodotto *= pb[i]; 



//calcola il prodotto di 1-x 

result = (1 - pb[0]); 

for( int i = l; i<pb.length; i++ ) 

A 

result *= (1 - pb[i]); 



return prodotto / ( prodotto + result ); 

} 

si noti che F array di float passato come para- 
metro potrebbe essere di qualsiasi lunghezza. 
Per prima cosa viene calcolato il prodotto 
delle probabilità, in seguito viene calcolato il 
prodotto di tutte le probabilità 1-x. 



Il\l ESECUZIONE 

Il valore ritornato dal metodo filtra() è un 
valore float che può assumere un valore vici- 
no allo zero. In questo caso il messaggio è 
accettato. Se il valore è invece superiore a 0.9, 
il messaggio è molto probabilmente posta 
indesiderata. 

Nella classe FiltroBayesiano sono presenti 
metodi di utilità per eseguire queste valuta- 
zioni e stampare un messaggio a video. Il 
metodo main() contiene del codice di prova, 
che esegue il filtro a fronte di messaggi spaz- 
zatura (bad) o legittimi (good): 



public static void main(String[] args) throws IOException 

{ 

Dizionario dizionarioJunk = new 

Dizionario("junk.mbox"); 
dizionarioJunk. importa(); 

Dizionario dizionarioNormale = new 

Dizionario("normale.mbox"); 
dizionarioNormale. importa(); 

FiltroBayesiano filtro = new FiltroBayesiano( 

dizionarioNormale, dizionarioJunk); 



filtro.stampaEsitoFile("bad.txt"); 



filtro.stampaEsitoFile("badl.txt"); 



filtro.stampaEsitoFile("good.txt"); 



filtro.stampaEsitoFile("goodl.txt"); 




l'output che si ottiene è simile al seguente: 

Importata la casella junk. mbox per un totale 
di 11481 token 

Importata la casella normale. mbox per un 
totale di 58850 token 

>» Il messaggio è posta spazzatura con una 
probabilità di 0.99949765 

>» Il messaggio è posta spazzatura con una 
probabilità di 0.9999999 

>» Il messaggio è posta accettata con una 
probabilità di 0.0 

>» Il messaggio è posta accettata con una 
probabilità di 0.0 

come si nota, i messaggi sono stati corretta- 
mente identificati. In alcuni casi con una pro- 
babilità dello 0.99 periodico. In realtà, la 
soglia dello 0.9 è relativa, perché con questa 
formula si ottiene quasi sempre un valore 
zero o molto vicino all'uno. 

Massimiliano Bigatti 



CHI E PAUL GRAHAM? 



Lu^K 



Per eseguire il 
programma lanciare la 
classe FiltroBayesiano, 
dalla directory che 
contiene il codice 
digitare, da console: 

java -cp . it. bigatti 
.antispam. FiltroBayesiano 



Gli algoritmi descritti 
in questo articolo 
sono una 
implementazione 
adattata di quanto 
discusso nell'articolo 
di Paul Graham, "A 
pian for spam" 
( http://www.paulgraham 



■com/spam.html) . 
Questa pubblicazione 
è stata la prima a 
portare in evidenza 
la possibilità di 
utilizzare il teorema 
di Bayes per gestire il 
problema della posta 
spazzatura. 



Le idee di Graham 
sono state poi 
raffinate da lui 
stesso in successive 
pubblicazioni e molto 
probabilmente da chi 
ha implementato via 
software queste 
teorie. 



http://www.ioprogrammo.it 



Aprile 2005/ 81 ► 



SECURITY T I Metodi per la gestione della sicurezza 



Come difendersi dagli attacchi dei pirati 

Hacker 

semaforo rosso 

È necessario utilizzare tutte le possibili accortezze per prevenire 
attacchi di tipo Denial of Service, considerando che un servizio non 
attivo fa perdere guadagni e, a lungo andare, credibilità 





I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 




i7^ Nozioni base di Java, 



Tomcat, JSE 



^m^M^\^\^\ 



Tempo di realizzazione 



La natura "pubblica" di un server Web lo rende 
potenzialmente vulnerabile ed esposto a 
diversi tipi di attacchi. In particolare è pos- 
sibile che un utente malintenzionato possa [1]: 

• accedere a risorse per cui non è autorizzato (e 
impadronirsi di informazioni riservate o mani- 
polare dati visibili ad altri) 

• utilizzare il server Web in modo improprio (per 
esempio utilizzarlo per perpetrare ulteriori 
attacchi "nascondendo" Y origine dell'attacco, 
utilizzare le risorse del server per memorizzare 
dati non autorizzati e impropri) 

• effettuare attacchi che portano ad un Denial of 
Service. 

Ovviamente non sono menzionati attacchi "fisici", 
come il rubare l'hardware o avere accesso diretto al- 
la console del server. Accanto agli attacchi di un 
utente è possibile che il server Web venga in contat- 
to con Virus o Worms; anch'essi possono provocare 
danni al sistema e produrre gli stessi effetti di attac- 
chi Denial Of Service. In ogni caso è sempre più vero 
che ad agire non è un utente ma una serie di tool 
automatici comandati (o programmati) da utenti 
malintenzionati. È comune trovare su internet tool e 
strumenti di test che possono essere, con poca diffi- 
coltà, adattati per perpetrare attacchi a sistemi re- 
moti. Ma cosa si intende con Denial of Service'? 



DENIAL OF SERVICE 

Con il termine Denial of Service (o semplicemente 
DoS) si identificano una serie di azioni volte a rende- 
re uno o più servizi non disponibili ad un gruppo di 
utenti autorizzati per un certo periodo di tempo; se 
il focus si concentra su un servizio reso disponibile 
in rete, si può anche parlare di Network Denial of 



Service; lo scopo di tali azioni è provocare un consu- 
mo (o un comportamento) anomalo di un insieme 
di servizi tanto da renderli inutilizzabili [2]. Quando 
l'attacco avviene da più di una sorgente di parla an- 
che di Distributed DoS (DDoS). 
Caso 1: una falla di SQL Server permetteva ad un at- 
taccante di inviare una particolare sequenza di byte 
e di eseguire, sull'istanza del SQL Server attaccato, 
del codice a suo piacimento. Un warm sfruttava 
questa falla per attaccare un sito e far partire da esso 
nuovi attacchi ad indirizzi generati in maniera ca- 
suale. Questo worm ha causato enormi danni, sia 
perché ha generato problemi DoS sui siti attaccati 
sia perché ha generato un altissimo volume di traffi- 
co su Internet, rallentandone notevolmente le nor- 
mali operazioni. L'unico modo per proteggere que- 
sto tipo di attacchi è quello di installare le patch per 
la versione di SQL che è vulnerabile oppure "na- 
scondere" tale server dietro un firewall e renderlo 
inaccessibile dall'esterno. 

Caso 2: con lo stesso principio, ovvero sfruttando 
una falla di sicurezza, un warm può attaccare nume- 
rosi siti. Ma anziché compromettere il loro funzio- 
namento, si limita a far eseguire da essi una serie di 
attacchi verso un unico sito, che è il vero obiettivo 
dell'attacco (attacco di tipo DDoS). In questo modo 
il sito attaccato consuma rapidamente le sue risorse. 
In questo caso un semplice firewall non basta, in 
quanto non riesce a distinguere le richieste prove- 
nienti da utenti "normali" e richieste da siti compro- 
messi dal worm. L'unico modo è rendere non attac- 
cabili i siti ove il worm si potrebbe propagare. 



DIVERSI TIPI DI DOS 

Secondo lo stack OSI, si possono distinguere sette 
livelli concettuali, da quello fisico a quello applicati- 
vo. I protocolli di Internet si possono collocare a di- 



► 82 /Aprile 2005 



http://www.ioprogrammo.it 



Metodi per la gestione della sicurezza ■ T SECURITY 



versi livelli (Figura 1, adattata da [2]) e possiamo di- 
stinguere, in base ad essi, diversi tipi di attacchi DoS 
in base al livello OSI interessato. Resta inteso che at- 
tacchi DoS ad uno specifico livello compromettono 
tutti i livelli successivi (più alti): per questo motivo la 
maggior parte delle tecniche per aumentare la sicu- 
rezza e difendersi da attacchi DoS si è focalizzata 
sugli strati bassi, tralasciando spesso la sicurezza 
relativa agli strati alti (e in particolare per quanto 
concerne il livello applicativo). Questo articolo, per 
contro, offre esempi e possibili soluzioni per il livel- 
lo applicativo. 



( Protocolli Internet ) 

( TCP, UDP, ICMP ) 

( DNS ) 

(IP) 

( ARP ) 


OSI 




Attacchi DoS 




Application 




Application 
DoS 




Presentation 


Session 








Transport 


/ Transport \ 

{ Dos ; 


Network 










Network 
DoS 




Datalink 


Physical 











Fig. 1 : II modello OSI e i diversi tipi di attacchi DoS 



PROBLEMI APERTI 

Mentre è comune che un'azienda si prepari ad af- 
frontare attacchi DoS di basso livello, attrezzandosi 
con firewalls, routers e configurando in maniera op- 
portuna application servers, spesso viene trascurata 
la difesa da questi tipi di attacchi a livello applicati- 
vo. Tra le cause di questa mancanza possiamo ricor- 
dare [4]: 

• Mancanza di standard aziendali per la sicurezza 
nelle applicazioni sviluppate 

• Carente cultura degli sviluppatori software rela- 
tivamente alla sicurezza; questo porta a conside- 
rare l'uso di protocolli o infrastrutture "sicure" 
(SSL, https e così via) sufficiente per garantire la 
sicurezza delle applicazioni; oppure si genera la 
falsa sicurezza nell'uso di protocolli (proprietari) 
non documentati 

• Eccessiva attenzione al "t ime to market" che por- 
ta a privilegiare il funzionamento "di base" del- 
l'applicazione senza considerare opportuna- 
mente la sua sicurezza; questo avviene a causa 
delle sempre maggiori pressioni del mercato e/o 
del management che privilegia il rilascio del 
software il prima possibile, anche a scapito di 
feature avanzate (ma spesso essenziali) 

Ognuna delle problematiche esposte, se non affron- 
tata attentamente, porta a possibili vulnerabilità ad 
attacchi di tipo DoS. Ma in concreto, a cosa è neces- 
sario prestare attenzione? 



PRIMA REGOLA: NON 
RIVELARE MAI TROPPO 

Anche se in crittografia vige la regola per cui non si 
deve mai fare affidamento sul fatto che il "nemico" 
(in questo caso chi vuol compromettere il sistema) 
manchi di informazione (sia essa sul tipo di algorit- 
mi utilizzati sia sul tipo di strumenti) è anche vero 
che rivelare queste informazioni agevola e, per lo 
meno, velocizza il compito a possibili malintenzio- 
nati. Pertanto è bene "oscurare" qualunque informa- 
zione non necessaria al corretto funzionamento del- 
l'applicazione e degli strumenti che ne fanno uso. 
Per esempio il server Web potrebbe essere configu- 
rato per non rivelare il suo produttore e/o versione; 
se si usano tool di sviluppo meglio disabilitare tutti i 
messaggi predefiniti e cambiare nome ai servizi 
standard o farli rispondere su porte che non sono 
quelle di default. Un'attenzione particolare va posta 
nella stampa di messaggi di errore in seguito ad 
eccezioni: è meglio rivelare il minimo possibile, in 
modo che un attaccante non possa "estrapolarne" 
informazioni utili (ovviamente è dannosissimo rive- 
lare password/nomi utente, ma è opportuno filtrare 
anche messaggi di errore provenienti da dbms o 
altre componenti in modo da non rivelarne il tipo o 
la versione e nemmeno il tipo di tabelle in uso o il 
nome dei server). 



ERRORI BLOCCANTI E NON 

È necessario prevedere a quali tipi di errori può an- 
dare in contro l'applicazione. Ognuno di questi erro- 
ri va gestito nel modo appropriato. Si supponga, per 
esempio, che un'applicazione che eroga un certo 
servizio gestisca un file di log. È inopportuno che er- 
rori nella creazione del log vadano ad incidere sulla 
funzionalità stessa! Allo stesso modo vanno identifi- 
cati accuratamente tutti i tipi di errore bloccanti e 
quelli non bloccanti; in seguito è necessario prende- 
re opportune contromisure, sia per segnalarli sia per 
gestirli. Una particolare cura va posta nella gestione 
di chiavi progressive persistenti. A livello teorico non 
esiste mai un numero troppo elevato progressivo 
prima che un certo programma si blocchi: molto 
meglio creare dei progressivi "a rotazione" (per 
esempio progressivi all'interno di un anno o all'in- 
terno di un periodo temporale più ristretto). 



BUFFER OVERFLOWS 
E VALIDAZIONE 
DELL'INPUT 

Ogni qualvolta un servizio accetta dei dati dall'ester- 
no deve prevedere un comportamento non destabi- 
lizzante in presenza di input errato. In particolare, 
una delle cause più comuni di vulnerabilità applica- 





GLOSSARIO 



CGI 

(Common Gateway 
Interface) modalità 
standard per la 
generazione di 
contenuti dinamici sul 
Web 



GARBAGE 
COLLECTOR 

Meccanismo (di solito 
asincrono e built-in nel 
linguaggio) per 
l'effettiva pulizia degli 
oggetti in memoria 
non più utilizzabili 
dall'applicazione. 



http://www.ioprogrammo.it 



Aprile 2005/ 83 ► 



SECURITY T 



Metodi per la gestione della sicurezza 





JMX 

JMX sta per Java 

Management 

Extensions ed è 

un'interfaccia standard 

per il monitoraggio e il 

controllo delle 

applicazioni Java 




Fig. 2: Riferimenti circolari 



riva è la mancata gestione del buffer overflow. Que- 
sto avviene ogniqualvolta ci si aspetta una dimen- 
sione massima per un determinato parametro o 
valore e quest'ultimo eccede tale limite. Se non ci 
sono controlli possono crearsi pericolose falle di 
sicurezza per tutte quelle applicazioni in cui un 
simile tipo di errore fa accedere a zone di memoria 
non protette (non è il caso di Java, ma di solito sono 
a rischio le applicazioni CGI). Anche la validazione 
dell'input può presentare problemi. Esistono due 
tecniche per prevenire un input non valido: 

• validazione positiva 

• validazione negativa 

la prima identifica tutte e sole le occorrenze valide 
dell'input (di solito attraverso operazioni di pattern 
matching o di espressioni regolari), la seconda iden- 
tifica stringhe errate (per esempio indica se una 
stringa contiene caratteri non validi). Ai fini della si- 
curezza è sempre da preferire la prima soluzione, in 
quanto se identificano tutti gli input validi si è sicuri 
di non incontrare problemi; è più difficile riuscire a 
trovare regole generali in modo da definire tutti gli 
input non validi (di solito si eseguono pattern mat- 
ching - uno per ogni carattere non valido - ed è faci- 
le tralasciarne alcuni). Alcuni problemi legati ad una 
cattiva gestione della validazione dell'input sono il 
code injection e il cross side scripting o XSS (per la 
vastità delle implicazioni connesse e per fornire ade- 
guati esempi e contromisure, questi problemi ver- 
ranno analizzati in un prossimo articolo). 



DIFENDERSI DAL 
CONSUMO DI RISORSE 

È già stato evidenziato come è importante adottare 
le opportune contromisure il prima possibile (si ri- 
cordi lo stack OSI). Per questo motivo è possibile im- 
postare opportune regole per limitare l'utilizzo di 
servizi da parte di una fonte (per esempio si ricorre 
a regole su firewall o routers). Però, a livello applica- 
tivo, è possibile conoscere alcune caratteristiche in- 
trinseche dei servizi offerti 
che non è possibile cono- 
scere a più basso livello. Un 
caso esemplificativo si ha 
quando ci si trova nella si- 
tuazione in cui un servizio 
ha la necessità di eseguire 
numerose computazioni 
(nonché accessi a risorse 
esterne quali database, file 
system di rete o altro) e per 
questo è particolarmente 
lento nel fornire i risultati. In 
questi casi il servizio è po- 



tenzialmente a rischio di attacchi DoS ed è ne- 
cessario prevedere opportune contromisure; il 
luogo più adatto è a livello applicativo. In questi casi 
si potrebbe, per esempio: 

• limitare il numero di possibili invocazioni al ser- 
vizio per tutti gli utenti (per esempio non posso- 
no essere soddisfatte contemporaneamente più 
di 10 richieste). Tale gestione può essere fatta 
con un pool di thread, dove ogni thread rispon- 
de ad una richiesta; esauriti i thread a disposi- 
zione, eventuali richieste restano in attesa di un 
thread che si liberi; 

• limitare il numero di invocazioni per singolo 
utente (dove l'utente può essere identificato in 
maniera "sicura" attraverso l'uso di certificati 
digitali o in maniera "debole" con uso di userna- 
me/password o IP address); queste limitazioni 
sono, di solito, applicate su un certo intervallo di 
tempo (per esempio non più di 10 invocazioni al 
minuto). 

Soluzioni come queste permettono all'applicazione 
di non "esaurire" le risorse del sistema e il servizio 
pur essendo ritardato non va in blocco (si ha un 
degrado delle prestazioni che non porta a DoS). 



GESTIONE 
NON CORRETTA 
DELLE RISORSE 

Benché possa sembrare strano, il più delle volte so- 
no le applicazioni stesse ad essere mal progettate e a 
portare a problemi di esaurimento delle risorse di- 
sponibili. Questo porta a un problema DoS anche in 
mancanza di attacchi specifici, ma in seguito all'uso 
intensivo (normale) delle applicazioni. Essenzial- 
mente il problema è nel mancato rilascio delle risor- 
se utilizzate o in un cattivo uso dei meccanismi di 
concorrenza. Nel primo caso si ha un progressivo 
esaurimento delle risorse; nel secondo caso si pos- 
sono avere processi in attesa infinita. Il problema 
più sentito, e tra i più difficili da identificare, è quel- 
lo relativo al progressivo consumo di memoria do- 
vuto a memory leak. Un memory leak è una porzio- 
ne di memoria che risulta in uso anche quando que- 
sto non è più vero. Questo avviene per lo più in lin- 
guaggi come il C++ che fanno uso di puntatori e che 
richiedono allo sviluppatore una corretta gestione 
della memoria, oppure in linguaggi con garbage col- 
lector che soffrono di alcune limitazioni (per esem- 
pio che usano un contatore per memorizzare il nu- 
mero di reference agli oggetti: nel caso di riferimen- 
ti circolari, esemplificati in Figura 2, non riescono a 
liberare la memoria). Purtroppo anche Java può sof- 
frire di memory leak, nonostante gli algoritmi im- 
plementati nel suo garbage collector siano immuni 



► 84 /Aprile 2005 



http://www.ioprogrammo.it 



Metodi per la gestione della sicurezza ■ T SECURITY 



dal problema delle referenze circolari. 



CONTROLLO 

DELLE RISORSE IN JAVA 

Java può essere considerato uno dei principali lin- 
guaggi di programmazione lato server per servizi 
pubblici sul Web. Esistono casi in cui il garbage col- 
lector di Java non funziona come dovrebbe e l'appli- 
cazione presenta dei memory leak. Infatti il garbage 
collector riesce a liberare solo quegli oggetti che non 
sono più referenziati da oggetti attivi. Ma che accade 
in presenza di variabili con riferimenti attivi ad og- 
getti con scope (e quindi ciclo di vita) diversi? Un ca- 
so concreto: le librerie AWT e i JavaBean fanno uso 
intensivo del design pattern Listener. In pratica se un 
oggetto A è interessato agli eventi di un'istanza B, A 
si registra come ascoltatore (listener) di B. A questo 
punto B contiene un reference ad A Se A ha un ciclo 
di vita maggiore di B e non si elimina il listener (at- 
traverso un opportuno metodo), B rimarrà in me- 
moria e non potrà essere recuperato dal garbage col- 
lector nemmeno quando il suo ciclo di vita sarà 
esaurito. Altre fonti di memory leak sono in alcune 
implementazioni del design pattern "singleton". Per 
una trattazione approfondita si rimanda a [5]. 
Esistono poi casi in cui è il linguaggio stesso ad avere 
dei bug che portano a memory leak (è il caso dell'u- 
so di StringBuffer bella versione 1.4.1 del linguaggio, 
http://bugs.sun.com/bugdatabase/view_bugdo7bug_ 
id-4724129). Un modo per verificare la presenza di 
memory leak è ricorrere a tool di profilazione come 
JProbe o altri prodotti commerciali; ma Java ha a di- 
sposizione una nuova tecnologia per il controllo del- 
le applicazioni: JMX. La descrizione approfondita 
della tecnologia esula dagli obiettivi di questo arti- 
colo, ma si possono trovare interessanti caratteristi- 
che per il controllo del consumo delle risorse nelle 
applicazioni che ne fanno uso. Infatti è possibile ve- 
rificare il consumo della memoria di ogni singola 
applicazione e di monitorare nel tempo tale consu- 
mo; per un esempio concreto si può vedere la libre- 
ria di tag JSP JMX Memory Monitor", presente alla 
pagina http://dev2dev. bea. com/codelibrary/code/jmx 
jnemory.jsp). 



IMPORTANZA DEL TEST 
E DELL'AGGIORNAMENTO 

I test non debbono essere solo funzionali: è necessa- 
rio preventivare possibili accessi non autorizzati, 
consumi di risorse di almeno un fattore oltre a quel- 
lo massimo previsto e input diversi da quelli d'uso 
normale. Purtroppo non è possibile, ad oggi, preve- 
dere dei test esaustivi per coprire tutte le possibili 
falle di sicurezza ma è sempre consigliabile, a livello 



aziendale, predisporre dei test automatici standard 
per le più comuni casistiche e, in particolare, test di 
carico e test di modulo con diversi input. Tra le rego- 
le d'oro della sicurezza c'è poi quella di mantenere 
aggiornati tutti i componenti software del sistema 
(dal sistema operativo, all'application server fino 
alla piattaforma software). 



MINIMO PROFILO 

Infine è da segnalare un consiglio sempre valido: 
mai permettere all'applicazione di operare su por- 
zioni di sistema non necessarie e mai permetterle 
accesso a risorse non preventivate. È sempre possi- 
bile che un'applicazione o una sua componente 
contengano dei bug che possono portare ad una 
vulnerabilità. È buona norma accertarsi che qualun- 
que applicazione sia eseguita con privilegi minimali 
e strettamente necessari al suo corretto utilizzo. 
Questo ovviamente per tutti gli ambienti enterprise 
dove sia gli utenti che le applicazioni possiedono 
propri profili. È assolutamente sconsigliabile che 
una qualsiasi applicazione che colloqui con il mon- 
do esterno abbia diritti di super user o root. 



CONCLUSIONI 

Come si è visto nell'introduzione dell'articolo at- 
tacchi di tipo DoS sono solo un esempio dei possi- 
bili attacchi ad un server Web. Questa notevole 
diversità di tipi di attacchi porta a definire, nell'in- 
sieme, un certo numero di contromisure, ognuna 
più appropriata per contrastare determinate azioni 
ma, nel complesso, coordinate e il più possibile 
complete. In letteratura è comune trovare il termi- 
ne u defence in depth" (Figura 3) per indicare un 
piano strategico di possibili contromisure, ognuna 
focalizzata ad un diverso livello di astrazione e di 
implementazione. In figura si possono notare le 
diverse contromisure comunemente adottate ai 
vari livelli [3]. 

Ivan Venuti 






^^^ Difesa di perimetro ^"N^ 

^r Packet Filtering, ^V 
f State-full Enspection ^W 
IDS ^ 








Difesa dell'Host 

Server Hardering, Host EDS 








Difesa Applicativa 

lt'.::.; "ezz* -e -:±.±- '.' e: . a; ■. -,■-:■■ 
politiche di sicirezza nel codice 


















BIBLIOGRAFIA 



[1] ASUMMARYOF 

DOS/DDOS 

PREVENTION, 

MONITORING AND 

MITIGATION 

TECHNIQUES IN A 

SERVICE PROVIDER 

ENVIRONMENT 

M. Glenn 

(SANS Institute) 

2003 

[2] WHAT DO WE MEAN 
BY NETWORK DENIAL 
OF SERVICE? 
G Shields 

http://www.cs.georgetow 
ri.edu/~clay/research/pubs 
/shields-ndos.pdf 

[3] WEB SERVER 

SECURITY GUIDELINES 

(CERT-ln) 

2004 

CISG-2004-04.pdf 

[4] APPLICATION 

DEVELOPMENT 

TECHNOLOGY AND 

TOOLS: 

VULNERABILITIES AND 

THREAT 

MANAGEMENT WITH 

SECURE 

PROGRAMMING 

PRACTICES, A DEFENSE 

IN-DEPTH 

APPROACH 

V. L Ankolekar 

GSEC 

2003 

[5] PLUGGING MEMORY 

LEAKS 

T.K.T. Leung 

(Java Pro) 

giugno 1999 



Fig. 3: defence in depth 



http://www.ioprogrammo.it 



Aprile 2005/ 85 ► 



ELETTRONICA T ■ Delphi Elettronica e GPS 



Un sistema GPS con mappa geografica 



Mettiamo la 
mappa nel GPS 

Avendo a disposizione un GPS, ci divertiremo a realizzare un sistema 
di acquisizione dei dati e a disegnare la traccia degli spostamenti su 
una mappa 





I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



wj- REQUISITI 



■ imi imi imi m 

Ipj^ Programmazione 
JS? Delphi, concetti base 
di elettronica 



S.O. Win 9.x, ME, 2000, 
' NT, XP 



^3 ^2^3 



Tempo di realizzazione 



Siamo giunti al terzo appuntamento dedicato 
alla realizzazione di un sistema completo di 
interfacciamento con ricevitori satellitari GPS: 
nel primo articolo abbiamo analizzato le principali 
funzioni del protocollo NMEA, utilizzato per lo 
scambio di informazioni tra apparati di navigazione, 
abbiamo descritto inoltre la realizzazione di un si- 
stema completo anche dal punto di vista elettronico, 
utilizzando il modulo ricevitore satellitare GEOGAR 
Nel secondo appuntamento è stato realizzato un 
sistema di acquisizione dei dati di posizione e quota 
e degli spostamenti di una piattaforma dotata di 
GPS. In questo terzo incontro proporremo le meto- 
dologie di inserimento e gestione di una cartina geo- 
grafica, che permetta la visualizzazione grafica della 
posizione, oltre che dei dati numerici di latitudine, 
longitudine geografica e di quota. 



LE CARTE GEOGRAFICHE 

Dal punto di vista geometrico possiamo pensare ad 
una carta geografica, come ad una proiezione della 
rappresentazione sferica del nostro pianeta rispetto 
ad una superficie piana. Supponiamo di avere a 
disposizione un mappamondo dotato di illumina- 
zione interna e di avvicinare ad esso una serie di 
fogli di carta piegati in modo appropriato. La prima 
idea che ci verrebbe sarebbe probabilmente quella 
di avvicinare al nostro ipotetico proiettore terrestre 
un foglio di carta disposto in senso piano, ma ben 
presto scopriremmo che la rappresentazione della 
proiezione della sfera sulla carta geografica, sarebbe 
accurata in un solo punto: questa rappresentazione 
viene infatti utilizzata per le carte polari, dove i meri- 
diani convergono nel polo geografico e le linee di 
uguale latitudine, sono quindi rappresentate come 
cerchi, questo particolare tipo di mappa si chiama a 
proiezione stereografica polare. Supponiamo di pie- 



gare il nostro foglio fino a realizzare un cilindro di 
diametro uguale alla sfera dell'ipotetico proiettore 
terrestre e di avvolgervi il mappamondo luminoso. 
La proiezione che otterremmo una volta disegnati i 
contorni sul foglio, e dopo averlo srotolato, avrebbe 
meridiani e paralleli perpendicolari tra loro come su 
di un foglio di carta millimetrata. La proiezione in 
questione si dice di Mercatore, che ha svariate carat- 
teristiche molto interessanti, tra le quali quella di 
potere effettuare una conversione diretta tra coordi- 
nate geografiche e posizione cartesiana sulla 
mappa: nella nostra applicazione utilizzeremo que- 
sto tipo di carte geografiche. Dal punto di vista pra- 
tico è possibile scaricare molte mappe dalla rete, 
ovviamente registrandosi ed acquistando le carte, 
che nella maggior parte dei casi sono protette da 
diritti di copyright. 



IL NOSTRO 
PROGRAMMA 

Siul sito di ioProgrammo all'interno della sezione 
doznload, utilizzando le password contenute nella 
pagina dell'editoriale, potrete scaricare il program- 
ma completo a cui facciamo riferimento in questo 
articolo, in cui sono elaborate anche le funzioni di 
acquisizione dati dal modulo GPS che abbiamo trat- 
tato in precedenza. Al momento della ricezione dei 
dati dal GPS, lanciando il programma sul PC ed 
effettuando la connessione al GPS, tramite l'opzione 
'Connect to GPS' dal menu GPS, si nota il flusso di 
informazioni NMEA nella finestra 'NMEA Raw infor- 
mations', in questo articolo spiegheremo comle 
visualizzare le coordinate e la posizione su una 
mappa come a proiezione cilindrica di Mercatore: 
questo tipo di mappe sono scaricabili da molti siti 
web, previa registrazione e talvolta a seguito del 
pagamento dei rispettivi diritti di copyright. 



► 86 /Aprile 2005 



http://www.ioprogrammo.it 



Delphi Elettronica e GPS ■ T ELETTRONICA 



È buona norma utilizzare mappe che diano delle 
indicazioni precise sui limiti degli estremi delle 
coordinate della mappa, questo ci servirà infatti per 
calibrare correttamente i riferimenti. 



IL CODICE SORGENTE 

Come di consueto cercheremo di produrre un codi- 
ce semplice e lineare, preferendo senz'altro in que- 
sta sede la chiarezza di esposizione eventualmente 
anche rispetto all' ottimizzazione del programma, 
per ovvi scopi didattici. Per l'acquisizione dei dati 
viene usato l'ottimo componente freeware 'CPDrv 
.pas' che può essere scaricato gratuitamente dal Web 
(Cdd4.zip). La procedura FormCreate, eseguita al 
momento della creazione della form principale, ha 
lo scopo di visualizzare la finestra iniziale contenen- 
te licenza e disclaimer, di inizializzare le variabili di 
posizione del sistema ed infine predisporre la forma 
grafica della form. Il codice proposto é il seguente: 

procedure TGPSPositionPlotterMainForm.FormCreate( 

Sender: TObject); 

var 

GPSPositionPIotterAboutdlg : TGPSPositionPIotterAboutBox; 

I,Xc,Yc:Integer; 



begin 



// About Dialog 



GPSPositionPIotterAboutdlg := nil; 



GPSPositionPIotterAboutdlg : = 
TGPSPositionPlotterAboutBox.Create( Self ); 

GPSPositionPIotterAboutdlg .ShowModal; 

// Initial Position 

InitialPositionl_at:=45; InitialPositionl_on: = 15; 



Startup:=True; 



//Graphic Map 



CurrentFile: = 'Mondo.BMP'; 



Mapscale: = 10Q0; //l pixel equal to 1,8 mt 

MapImage.Picture.LoadFromFile(CurrentFile); 
Maplmage. Canvas.Pen. Color :=clYellow; 

MapImage.Canvas.Brush.Style:=bsClear ; 

xc: = ( MAPPanel.Width div 2); 

yc: = (MAPPanel.Height div 2); 

For I:=0 to 8 do begin 

Maplmage. Canvas.Ellipse((Xc-(I*50)),( 

Yc-(I*50)),(Xc+(I*50)),(Yc+(I*50))); 

end; 

//Map Coordinates 

MapExtremitiesChange; 

end; 



Notate l'istruzione "CurrentFile:- 'Mondo.BMP';" 
che prelude all'utilizzo di carte geografiche in for- 
mato bitmap e che predispone il sistema ad aprire la 
mappa di default rappresentante tutto il globo terre- 
stre attraverso l'istruzione "Maplmage. Picture 
.LoadFromFile(CurrentFile);". 



Qualora l'utente decidesse di ridimensionare la fine- 
stra, viene eseguito l'event handler riportato di se- 
guito che provvede semplicemente a ricaricare l'im- 
magine relativa alla mappa corrente ed a ridisegna- 
re la sequenza di cerchi concentrici gialli di riferi- 
mento. 

procedure TGPSPositionPlotterMainForm.FormResize( 

Sender: TObject); 

Var 

I,Xc,Yc:Integer; 

begin 

Maplmage. Picture.LoadFromFile(CurrentFile); 

Maplmage. Canvas.Pen. Color :=clYellow; 

MapImage.Canvas.Brush.Style: = bsClear ; 



xc:=( MAPPanel.Width div 2); 



yc:=(MAPPanel.Height div 2); 



For I:=Q to 8 do begin 



Maplmage. Canvas.Ellipse((Xc-(I*50)),( 
Yc-(I*50)),(Xc+(I*50)),(Yc+(I*50))); 



end; 



end; 



Qualora l'utente cambi i valori geografici di riferi- 
mento della mappa, viene eseguita una delle quattro 
procedure che seguono, corrispondenti agli event 
handler dell'evento "OnChange" di ciascuna delle 
quattro caselle di edit poste sul lato sinistro della 
form principale, corrispondenti alle coordinate limi- 
te della cartina. Viene eseguita in ogni caso la proce- 
dura "MapExtremitiesChange" descritta poco più 
avanti. La procedura "MapExtremitiesChange" sprov- 
vede a convertire, innanzi tutto, una stringa conte- 
nuta in quattro caselle d'edit contenenti i valori delle 
coordinate, delle estremità della cartina, in valori 
numerici: se la conversione non è andata a buon 
fine viene visualizzato un messaggio d'errore. 
Il valore delle coordinate delle estremità della 
mappa vengono memorizzate nelle variabili globali 
LonLeft (Longitudine al lato sinistro), LonRight 
(Longitudine al lato destro), LatTop (Latitudine al 
margine superiore) e LatBottom (Latitudine al mar- 
gine inferiore). 

procedure TGPSPositionPIotterMainForm. 

MapExtremitiesChange; 

Var Code:Integer; 

begin 

//Manages Changes upon Map Parameters 

Val(MapLatTopEdit.Text, lattop, Code); 

//Error during conversion to integer? 

if Code <> then 
MessageDlg('Map coordinate Error: 
' + IntToStr(Code), mtWarning, [mbOk], 0); 

Val(MapLatBottomEdit.Text, latbottom, Code); 

//Error during conversion to integer? 



if Code <> then 





Realizzazione 

con modulo GEOGAP 



N1 
N1 



N2 
N2 



N2 
N2 
NT 



PCExplorer light 



Modulo Elisys 
GEOGAP 



Transistor BC 107 



Resistenza 
1Kohm 1/4W 



Resistenza 
10Kohm 1/4W 



Resistenza 
33Kohm 1/4W 



Condensatore 
100 nF 



Realizzazione con GPS 
N1 PCExplorer light 



NT 
NT 



GPS commerciale 



Cavo connessione 
(dipende dal 
modello di GPS) 



ACQUISTARE 
PC EXPLORER 
LIGHT 

L'apparecchiatura PC 
Explorer light è prodot- 
ta e commercializzata 
dalla Elisys s.r.l. e può 
essere acquistata al 
prezzo di € 213,60 nella 
versione light, € 99 
nella versione basic e 
€ 69 in kit (IVA inclusa) 
sul web all'indirizzo 
www.pcexplorer.it oppure 
inviando una e-mail a: 
pcexplorer@elisys.it, od 
anche telefonicamente 
al numero 0823/468565 
o via Fax al: 
0823/495483. 



MessageDlg('Map coordinate Error: 



http://www.ioprogrammo.it 



Aprile 2005/ 87 ► 



ELETTRONICA T 



Delphi Elettronica e GPS 




CONNESSIONE 
SERIALE: 

Il programma funziona 

acquisendo i dati dal 

GPS dalla porta seriale 

COMI, 9600 baud, 8 bit 

dati, 1 bit di Stop, se 

sul proprio sistema si 

intende utilizzare una 

porta differente, 

oppure parametri 

diversi da quelli citati è 

sufficiente variare i 

parametri di 

connessione del 

componente 

'SerialDriver' 

attraverso l'Object 

Inspetor di Delphi. 



' + IntToStr-(Code), mtWarning, [mbOk], 0); 

Val(MapLonLeftEdit.Text,lonleft, Code); 

//Error during conversion to integer? 

if Code <> then 
MessageDlg('Map coordinate Error: 
' + IntToStr(Code), mtWarning, [mbOk], 0); 

Val(MapLonRightEdit.Text,lonright, Code); 

//Error during conversion to integer? 

if Code <> then 
MessageDlg('Map coordinate Error: 

' + IntToStr(Code), mtWarning, [mbOk], 0); 

end; 



% GPS Position Plotter With Map 


File Map GPS Àbout and licence 


Tirine Latitude 


Longitude 

01655.: 


173021 4046.512 N 


la 


20 


LJ fi 


|-180 MAR |1S0 
|-90 



Fig. 1: 1 dati della cartina possono essere variati per 
mezzo di quattro caseiie di dialogo 

La procedura di gestione e lettura delle coordinate 
geografiche da parte del GPS, è stata adattata alle 
nuove funzionalità relative all'utilizzo delle carte 
geografiche. In sostanza questo frammento di codi- 
ce è stato variato nel calcolo della posizione da dise- 
gnare sulla mappa attraverso le istruzioni seguenti: 



// 



*NEW* 



Position Plot 



X:=Trunc(MapImage.Picture.Width/(LonRight-l_onl_eft) 

*((LonGradi + (LonPrimi/60)-LonLeft))); 

Y:=MapImage.Picture.Height-Trunc( 

MapImage.Picture.Height/(LatTop-LatBottom) 
*(LatGradi+(LatPrimi/60)-LatBottom)); 



XYLabel.Caption:='Map X:'+Inttostr(x)+' 



Map Y:'+ 
inttoStr(y); 



È possibile notare che in questa fase si tiene conto 
delle coordinate relative ai margini dell'immagine, 
individuate dalle variabili LonLeft (Longitudine al la- 

















■H 




















RE CE I VE DATA 








U 
O 
















O 






<D 






■H 
VI 




TRAHSMIT DATA 










ni 










PQ 













^ 






u 






-P 




GROUHD 


<D 






A 






B 










■H 








u 






U 
M 






OQ 








O 












■H 












S* 












n 
















tu 



















Fig. 2: Lo schema elettrico comprende la semplice connessione GPS-PCExplorer light tra- 
mite il cavo in dotazione al GPS 



to sinistro), LonRight (Longitudine al lato destro), 
LatTop (Latitudine al margine superiore) e LatBot- 
tom (Latitudine al margine inferiore). La posizione 
rilevata dal GPS (Latitudine e Longitudine) è stata 
suddivisa in gradi e primi, utilizzando le variabili 
LatGradi, LatPrimi, LonGradi, LonPrimi dal signifi- 
cato abbastanza ovvio. I valori di X e Y riferiti alla 
mappa vengono poi successivamente utilizzati per 
disegnare un cerchio rosso pieno della dimensione 
di 7 pixel di raggio centrato sulla rappresentazione 
grafica della posizione individuata sulla mappa. 
Per completezza e comodità di lettura si riporta la 
procedura nella sua totalità qui di seguito. 

procedure 

TGPSPositionPIotterMainForm.NMEApresentPosition; 
var 

stringline / s:string[255]; 

io,fo,ila,fla, ilo, fio, ialt,falt,v,m, code, X,Y: Integer; 

ora,lat,ns,lon,ew,quota,fm:string; 



feasible:Boolean; 



gra,pri:real; 



LatReal,l_onReal, Quota real, LatGradi, LatPrimi, LonGradi, 

LonPrimi:Real; 



begin 



Stringline: =GlobalString; 



begin 



(*Decodifico il formato NMEA GPGGA Global Position*) 
If copy(Stringline,l,6) = '$GPGGA' then begin 
io:=0; fo:=0; ila: =0; fla:=0; ilo: =0; flo:=0; ialt:=0; 



falt:=0; v:=0; ora: 



lat: 



lon: 



ns:= ; 
quota: 



fm: 



Feasible:=True; 



for m: = l to (length(stringline)-7) do begin 
If copy(Stringline,m,l) = ',' then v:=v+l; 
if v=0 then io: = m; if v=l then fo:=m; 

if v=l then ila:=m; 
if v=2 then fla:=m; if v=3 then ilo: = m; 

if v=4 then flo:=m; 
if v=8 then ialt:=m; if v=9 then falt:=m; 
(* Controllo se il GPS sta tracciando oppure no*) 



if fo>(io+l) then begin 



ora:=copy(Stringline,(io+2),(fo-io-l)); 



Feasible:=True; 



end 



else 



begin 



Feasible: = False; 



end; 



if fla>(ila+l) then begin 



lat:=copy(Stringline,(ila+2),(fla-ila-l)); 



Val( Lat,LatReal,code); 



ns:=copy(Stringline,(fla+2),l); 



Feasible:=True; 



end 



else 



begin 



► 88 /Aprile 2005 



http://www.ioprogrammo.it 



Delphi Elettronica e GPS ■ T ELETTRONICA 



Feasible: = False; 



end; 



if flo>(ilo+l) then begin 



lon:=copy(Stringline / (ilo+2) / (flo-ilo-l)); 



Val( Lon,l_onReal,code); 



ew:=copy(Stringline,(flo+2),l); 



Feasible:=True; 



end 



else 



begin 



Feasible: = False; 



end; 



if falt>(ialt+l) then begin 



quota :=copy(Stringline,(ialt+2),(falt-ialt-l)); 

fm:=copy(Stringline,(falt+2),l); 

Feasible:=True; 

end 

else 



begin 



Feasible: = False; 



end; 



end; 



if feasible then begin 



inc(GlobalRetrivedNMEAString); 



s:='NMEA Global Position and Altitude 

at:'+ora+' '+lat+' '+ns+' '+lon+' '+ew+' 
'+quota+' '+fm; 

label3.caption:=ora; label4.caption: = lat; 
labe!9.caption: = ns; 

label8.caption: = lon; label5.caption:=ew; 
label6.caption:=quota; 



label7.caption:=fm; 



// Graphic plot 



if (Startup and Feasible) then begin 

//First Coordinate 

InitialPositionLat: = LatReal; //Map Centre 
InitialPositionl_on: = l_onReal; 



Startup: = False; 



end; 



LatGradi:=Trunc(LatReal/10Q); 



LonGradi:=Trunc(LonReal/100); 



LonPrimi: = (LonReal-(LonGradi*100)); 

LatPrimi:=(LatReal-(LatGradi*100)); 

// OLD Position Plot 

//Y:= ( MAPPanel.Height div 2 )+Trunc(( 

InitialPositionLat-LatReal)*MapScale); 

//X:= ( MAPPanel.Width div 2 )+Trunc(( 

LonReal-InitialPositionLon)*MapScale); 



// 



*NEW*** Position Plot 



X:=Trunc(MapImage.Picture.Width/( 
LonRight-LonLeft)*((LonGradi+(LonPrimi/60)- 

LonLeft))); 

Y:=MapImage.Picture.Height-Trunc( 
MapImage.Picture.Height/(LatTop-LatBottom) 

*(LatGradi + (LatPrimi/60)-LatBottom)); 



XYLabel.Caption: 



'Map X:'+Inttostr(x)+' 

Map Y:'+ inttoStr(y); 



Maplmage. Canvas.Pen. Color :=clRed; 





Maplmage. Canvas 


Brush. Color 


:=clRed; 






Maplmage. Canvas 


Brush.Style 


= bsSolid; 






Maplmage. Canvas 


Ellipse((x-7),(v-7), 

(x+7),(y+ 


7)); 


end; 


end; 


end; 


end; 



Una nota finale è meritata dalle procedure di con- 
nessione: il programma funziona utilizzando la por- 
ta seriale COMI, che in alcuni PC viene utilizzata per 
la gestione del mouse, in questo caso per evitare 
conflitti di sistema è necessario variare i parametri 
di connessione del componente 'SerialDrivef. I pa- 
rametri di comunicazione della porta seriale vengo- 
no impostati come: COMI, 9600 baud, 8 bit dati, 1 
bit di Stop: se sul proprio sistema si intende utilizza- 
re una porta differente, oppure parametri diversi da 
quelli citati è sufficiente variare i parametri di con- 
nessione del componente 'SerialDrivef attraverso 
Y Object Inspetor di Delphi. 




Fig. 12: L'installazione del software di gestione avviene 
semplicemente eseguendo l'apposito programma 



CONCLUSIONI 

Il semplice utilizzo di un ricevitore satellitare inte- 
grato GPS, oppure di un qualunque modello com- 
merciale dotato di una porta d'uscita seriale, unita- 
mente al software presentato in questa sede e negli 
appuntamenti precedenti sono sufficienti per realiz- 
zare un sistema di misurazione della posizione, do- 
tato di mappe geografiche. Le applicazioni sono in- 
numerevoli, dai sistemi per auto e per barca ai quali 
siamo ormai abituati, ma anche nel campo dell'in- 
gegneria civile e della topografia. Il lettore vorrà 
comprendere che nonostante quanto esposto in 
queste pagine sia stato debitamente verificato e col- 
laudato, tuttavia viene riportato a scopo illustrativo 
e di studio, pertanto l'editore e l'autore non sono da 
considerare responsabili per eventuali conseguenze 
derivanti dell'utilizzo di quanto esposto in questa 
sede, soprattutto per la tipologia e la complessità 
dell'argomento. 

Luca Spuntoni 





^ SUL WEB 



Il sistema proposto in 
queste pagine è stato 
realizzato e collaudato 
con la apparecchiatura 
per il collaudo e la spe- 
rimentazione di circuiti 
elettronici con Personal 
Computer 'PC EXPLO- 
RER light': 

ulteriori informazioni 
su come si possa reperi- 
re questa apparecchia- 
tura è possibile visi- 
tare il WEB all'indirizzo: 

'http://www.pcexplorer.it' 

oppure 

'http://web.tiscali.it/spunt 

osoft/' 

od infine inviare una 

e-mail a: 

spuntosoft@tiscali.it. 



CONTATTA 




wi 



L'autore è lieto di 
rispondere ai quesiti 
dei lettori 

sull'interfacciamento 
dei PC all'indirizzo: 
luca.spuntoni@ 
ioprogrammo.it 



http://www.ioprogrammo.it 



Aprile 2005/ 89 ► 




CORSI BASE T 



I 



ASP.NET 




Gestire i dati sul Web con ASP.NET 



Data Controls e 
l'accesso ai dati 

L'accesso ai dati è una delle operazioni più diffuse nelle applicazioni web 
ed ASP.NET offre un comodo sistema, che si basa su ADO.NET tale a 
rendere facilmente implementabili soluzioni anche molto complesse! 




G CD Q WEB 

aspdotnet3.zip 



Va 




I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



jn 




REQUISITI 



U.).WM1M1MM 
frani HTML, ASP.NET 



. Microsoft .NET 
Framework 1.0 o 
successivi, ASP.NET 




LJ accesso ai dati è una componente fonda- 
mentale di qualsiasi applicazione web, dato 
I che nel 90% dei casi ciò che uno sviluppato- 
re fa non è altro che leggere o scrivere. Nell'arco degli 
ultimi anni, infatti, è diventato sempre più frequen- 
te manipolare informazioni salvate in formato XML, 
oltre che quelle classiche in un database. ASRNET, 
tecnologia moderna e destinata ad applicazioni en- 
terprise, non avrebbe potuto ignorarne l'evoluzione 
dell'accesso ai dati in questo senso. Per questo 
quando si parla di accesso ai dati con ASP .NET, ci 
riferiamo ad una qualsiasi fonte dati, sia esso un 
database oppure anche un più esotico file XML. 



ALLA BASE CE ADO.NET 

Acronimo di ActiveX Data Objects, ADO è un insieme 
di librerie pensate per favorire l'accesso ai dati. 
Quello che unisce ADO e ADO.NET è lo scopo: uni- 
ficare le metodologie di accesso ai dati a prescindere 
dalla fonte e dal linguaggio utilizzato. Ciò che divide 
queste due tecnologie è tutto il resto, in particolar 
modo la metodologia d'accesso ai dati. 



L'APPROCCIO 
DISCONIUESSO: IL DATASET 

Le differenze principali tra l'approccio di ADO ri- 
spetto a quello offerto da ADO.NET non si limitano 
alla comparsa di classi create appositamente per 
ogni database, in modo da migliorarne le perfor- 
mance, ma soprattutto modificano la modalità di 
accesso ai dati in senso "disconnesso". Questo ap- 
proccio privilegia dunque una "fotografia" dei dati, 
anziché un accesso sequenziale tipico del recordset 
di ADO. In realtà in ADO.NET sono previste entram- 
be le modalità di accesso, ma di sicuro la più utiliz- 









alia.com bok Blog Pattern! 




o-a-EE ì\pem h* 


zo httpif/localhos 


mp. , q ™ dq^px 








title 


link 






pub! ite 


descnption creator 


category 


ASP to ASP.NET 

: _ .■ '. 

Roadshowinll 


] aspi à: 


, 


ostra.aspx?rD=586 


Ita, 33 

2005 

HllQi 


ili ; t ..". ' .' 

Microsoft Italia 

applicazioni ASP verso 
àSP.NET articolato m 


Damele 

6c bieche 


FocusON 


#674 - Effettuare il 
ASP.NET 2.0 


http://www.aspitalia 


. sidus ■"' ' nj 


a £ p K ?rD=674 


Fri, 04 

Feb 

2005 

fOlOt 


introdotte daASP.NET 
effettuare il post di una 

L'oggetto... 


M .stai la 


eiivsciTpiglt 


#673 - Client 
CallBack con 
ASP.NET 2.0 


ì aspi lira 


.-»«,„ 


aspK?rD=673 


Con l'avvento di 
ASP NET 2 

a 03 ; :' n ... itemi 

..'..' : '.. 

2005 Client Calli 
Javascript (... 


Massimo 

liappelìese 


'• : •" ■ 










Dal 31 Gennaio al 04 




<l 


■- V 








,,nt™, 



Fig. 1: Repeater mostra i dati contenuti in un template 

zata è quella che prevede l'utilizzo di un DataSet. 
Come il nome stesso suggerisce, la classe DataSet è 
un contenitore di informazioni neutro, rispetto alla 
fonte dati, di informazioni. È composto da n Data- 
Table, ovvero da tabelle, che a loro volta sono com- 
posti da DataColumns (colonne) e DataRows (ri- 
ghe). In genere una DataTable, è riempita attraverso 
un DataAdapter, che non è altro che una classe par- 
ticolare che funge da ponte tra i dati veri e propri ed 
il DataSet. La particolarità del DataAdapter è che 
racchiude in sé tutta la logica necessaria ad aprire la 
connessione al database, effettuare la query, inserire 
i dati all'interno del DataTable e chiudere la connes- 
sione. Il vantaggio del DataSet rispetto alla lettura 
sequenziale, che resta supportata, è che diventa 
possibile "spostare" i dati che sono contenuti all'in- 
terno della collection più facilmente. Di fatto la col- 
lection è già popolata con tutti i dati che servono e 
non è più necessario ritornare alla fonte per recupe- 
rarli. D'altro canto in questo modo appare chiaro 
che i dati, una volta che il DataSet è stato popolato, 
possono essere differenti da quelli contenuti nella 
fonte dati anche solo dopo pochi attimi. 




^ 90 /Aprile 2005 



ASP.NET 



T CORSI BASE 



COME IL VECCHIO 

RECORDSET 

IL DATAREADER 

In realtà il DataAdapter, utilizza un metodo chiama- 
to Fili per ottenere le informazioni necessarie a 
riempire il DataSet. Fili non fa altro che istanziare 
una serie di oggetti per arrivare al proprio scopo. Tra 
questi spicca il DataReader, che in alcuni casi può 
essere referenziato anche come SqlDataReader o 
OleDbDataReader a seconda del data provider utiliz- 
zato. Si tratta di una classe che permette un accesso 
in sola lettura, in modalità for ward only (cioè, solo in 
avanti) ai dati, un po' come il recordset di ADO. Ri- 
spetto a quest'ultimo però ha diverse funzionalità in 
meno, ad esempio, non permette di utilizzare curso- 
ri particolari né di modificare i dati. Per posizionarsi 
sulla riga che si vuole leggere è sufficiente utilizzar- 
ne il metodo Read, mentre per le altre operazioni 
l'accesso alle informazioni è del tutto simile alle tec- 
niche già utilizzate per il Recordset di ADO. 



MOSTRARE I DATI: 
IL DATABINDiniG 

Dopo questa rapida occhiata alle classi che sono alla 
base di ADO.NET, è giunta l'ora di mostrare come 
ASRNET sfrutta queste classi per mostrare i dati al- 
l'interno di una pagina. Alla base di tutto c'è un 
meccanismo, supportato da molti dei controls di 
ASRNET, il Databinding. Letteralmente vuol dire 
"associazione di dati" ed infatti è un sistema con il 
quale si associano i dati estratti da una fonte dati ad 
un contenitore disposto in qualche punto sulla pagi- 
na. Questa fonte può essere un DataSet, una Data- 
Table, un DataReader, ma più in generale una qual- 
siasi classe che implementi una tra le interfacce 
IList, IListSource e IEnumerable. È così possibile fare 
il binding anche di collection personalizzate. L'asso- 
ciazione è effettuata utilizzando una classe partico- 
lare, chiamata Dataltem, che fa da ponte verso il 
contenitore verso e proprio dei dati: 

<%#Container.DataItem%> 

L'insieme dei caratteri <# %> dice al compilatore che 
si tratta di un'istruzione da utilizzare in fase di data- 
binding. 



I DATACOniTROLS 

Senza controls da utilizzare per visualizzare i dati, il 
databinding sarebbe inutile. Senza entrare troppo 
nei dettagli, perché esula dallo scopo di questo arti- 
colo, i Data Controls sono un insieme di controlli 
che permettono di associare i dati, sfruttando il 
meccanismo del Databinding, e visualizzarli nella 



^1ilti^hWhltillM^I#liiliil^tii-l-lll-H-li»ilNJ-H-lilliHfflWlffll'B ^J0J*1 


File Modifica Visualizza Preferiti Strumenti ? Collegamenti ^ ASPItalia.com Forum.ASPItalia.com bok Blog Patterns J> 


- O T b Indire:. hrrc ni i n dal a px zi 




titìe ìd 


titìe 


type pub ìdpnce ad les notes 


pub date 


BU1032 
BUI 111 


Executive' s 
Database Guide 


business 


1389 


19.990C 


5000,0000 


10 


4095 


Aii everaew i i i i database Systems wiiii 
ernphasis on coir application. 
Ulustrated. 


12/06/1991 
0.00.00 


'. . .Ijiiq uh '. .::r.-i'i>.:- 

ius Baiane e 
Sheets 


business 


1389 


11,9500 


5000,0000 


10 


3876 


tL.< _ 1 '_. ■■ J .i _i 
■f muti e: i'.o the best advantage 


09/06/1991 
0.00.00 


BU2075 


You Can Combat 
er Stress! 


business 


0736 


2,9900 


10125,0000 


24 


18722 


The latest medicai ' . i gical techmques 
for living with the • -e Easy-to- 
understand expla ìations 


30/06/1991 
0.00.00 


BIT7832 


Straight Talk About 
Cornputers 


business 


1389 


I9.990C 


5000,0000 


10 


4095 


Ariiiotated analysis of what computer? can do [or 
you: a no-hvpe guide for the entità! user 


22/06/1991 
0.00.00 


MC2222 


Silicon Valley 

ime Treats 


mod_coo k 


0877 


ì9,V;iV 





12 


2032 


V , . r- ,i-i , , - f , I ir 1 - > -j— -,, 1 ri- -1,11 
meals. 


09/06/1991 
0.00.00 


MC3021 


Tv '_ * .1 i l'i , 


mod.cook 


0877 


2,9900 


15000,0000 


24 


22246 


Traditional Freneh gourmet lecipes adapìed i 
modera microvrave cooksg 


18/06/1991 
0.00.00 


PC1035 


Butlslt User Friendly? 


popular_cornp 


1389 


22,95007000,0000 


16 


8780 


A survey of S'-'fhv re user, focusing 
on ti e 'friend! lesa' of each 


30/06/1991 
0.00.00 


PC8S8S 


Secreti of Silicon Valley 


popular_comp 


1389 


-"." 


8000,0000 


10 


4095 


Muckraking repo ■■ _ All': laigest 
computer hai iwarc and software manufai turers 


12/06/1994 
0.00.00 


PC9999 


Net Etiquette 


popular_comp 


1389 










must-ri ìi i. ori p itei 'iifì ern i is 


06/08/2000 
1.33.54 


PS1372 


Computer Phobic AND 

Hon-Phobic Li li. . ii 1 
1 i Vanations 


psychology 


0877 


21,59007000,0000 


10 


375 


àmusi for the specialista this bool examines ìlie 
differente betwei , iate and fear 

coinputers and ihose who don't 


21/10/1991 1 
0.00.00 


PS2091 


he Enemy? 


psychology 


0736 


10,9500 


2275,0000 


12 


2045 


Carefully researcl i e effeets of strong 

ernotioiìs on the body Metabottc chaits irickided. 


15/06/1991 ì 
0.00.00 


PS2106 


Life Without Fear 


psychology 


0736 


7,0000 


6000,0000 


10 


111 


New e.Ken::iae, meditation, an.d numnonal 
techmques that cari re dm: e the shock of daily 
mterachotis. t i «. audience, t t i metius 
nidi- ed,- <:<it..- 'i.'e . ■ t dJ. k ir.] un Uri,' 


05/10/1991 | 
0.00.00 

zi 


i eie completata 














| | | |*J Intranet locale 




Fig. 2: Un datagrid consente possibilità di ordinamento e paginazione 



pagina, sfruttando dei template per ripetere gli stes- 
si. I controls principali di questa famiglia sono tre: 

• Repeater: è il più semplice di tutti e fa esatta- 
mente una sola cosa molto semplice, ovvero ri- 
petere i dati contenuti nel template; 

• DataList: è una via di mezzo tra i controls presi 
in esame ed offre funzionalità più avanzate ri- 
spetto al repeater, lasciando comunque una cer- 
ta libertà di personalizzazione; 

• DataGrid: è il più completo tra quelli presenti, 
offre funzionalità di ordinamento, paginazione 
e modifica già incluse e facilmente implemen- 
tabili. 

La scelta tra uno di questi è dettata essenzialmente 
delle caratteristiche offerte, perché ad esempio il 
DataGrid ha meccanismi già pronti per paginazione 
ed ordinamento dei dati, mentre gli altri ne sono 
privi e per dotarli di queste funzionalità è necessario 



L'AUTORE 



Daniele Bochicchio è il 
content manager di 
ASPItalia.com, commu- 
nity che si occupa di 
ASP.NET, Classic ASP e 
Windows Server Sy- 
stem. Il suo lavoro è 
principalmente di con- 
sulenza e formazione, 
specie su ASP.NET, e 
scrive per diverse riviste 
e siti. È Microsoft ASP 
.NET MVP, un riconosci- 
mento per il suo impe- 
gno a supporto delle 
community e per l'espe- 
rienza maturata negli 
anni. Il suo blog è all'in- 
dirizzo http://blogs 
.aspitalia.com/daniele/ 



COM'È FATTO UN MAMAGED PROVIDER 



Un managed provider 
è composto da un 
insieme di classi, rag- 
gruppate per ordine e 
semplicità all'interno 
di un namespace parti- 
colare. Sono disponibi- 
li delle interfacce al- 
l'interno del namespa- 
ce System.Data .Comm 
che sono utilizzate da 
tutti gli altri per co- 
struire le implementa- 
zioni concrete proprio 
di ogni provider: 



IDbConnection 



IDbCommand 

IDbDataReader 
IDbDataAdapter 

Il punto di partenza di 
ciascun data provider 
è dunque creare quat- 
tro oggetti che imple- 
mentino queste inter- 
facce. In genere questi 
oggetti sono chiamati 
Connection, Com- 
mand, DataReader e 
DataAdapter e sono 



preceduti da un prefis- 
so specifico per il data 
provider. 

Ad esempio le classi 
proprie di SQL Server 
avranno il prefisso Sql 
nel nome e si trovano 
nel namespace 
System.Data.SqlClient, 
così come quelle OLE- 
db si riconoscono dal 
prefisso OleDb e sono 
conteneute nel name- 
space System .Da- 
ta.OleDb. 



Aprile 2005/ 91 * 





CORSI BASE T 



I 



ASP.NET 





scrivere molto più codice aggiuntivo. Per contro il 
DataGrid produce una tabella HTML, mentre il Da- 
taList e Repeater consentono flessibilità e spesso so- 
no utilizzati (specie quest'ultimo) per produrre an- 
che output di solo testo o in formato XML. 
Ciò che hanno in comune è la proprietà DataSource, 
che serve per specificare la sorgente dei dati, un 
metodo DataBindQ per associare questi dati, e tre 
eventi: 

• ItemCreated: scatenato all'aggiunta di ogni sin- 
golo item al Data Control; 



UN DATAGRID IN 2 PASSI 



Editate un file con il no- 
tepad o con un qualun- 
que editor di testo, riem- 
pitelo al suo interno con 
il contenuto estratto dai 
passi seguenti e salvate- 
lo nella root di US con il 
nome rss.aspx. Provate 



poi ad eseguire l'appl- 
icazione puntando il 
browser su http://local- 
host/rss. aspx. Quello che 
facciamo in questo 
esempio è collegare un 
controllo di tipo Repea- 
ter a un file XML conte- 



nente delle news in for- 
mato RSS. 

Tramite il control le mo- 
striamo a video in modo 
ordinato, sfruttando le 
capacità di lettura che 
quest'ultimo offre da 
qualsiasi fonte dati. 



LETTURA DI XML CON IL DATASET 



<%@ Import Namespace="System.Data" %> 



<%@ Import Namespace="System.Data.SqlClient" %> 



<SCRIPT language="C#" runat="server"> 
void Page_Load (Object sender, EventArgs e) { 
// creo il dataset 



DataSet ds= new DataSetQ; 



// leggo i dati dal file XML 



ds.ReadXml(Server.MapPath("feed.xml")); 



// estraggo tutti i nodi di nome item 
rp.DataSource = new DataView(ds.Tables["item"]); 
rp.DataBindQ; 



} 



</SCRIPT> 



Q Creiamo un nuovo oggetto di tipo Dataset chiamato ds. L'oggetto 
ds viene riempito con il contenuto del file feed.xml grazie al 
metodo ReadXml. Viene poi creato un Repeater a cui andremo ad 
associare tutti i dati estratti dal file XML, salvato nell'oggetto ds ed 
infine viene richiamato il metodo DataBind che fisicamente effettua il 
collegamento dei dati al controllo rp e li mostra a video. 

ASSOCIAMO IL DATASET AL DATA CONTROL 



<ASP:repeater id 
<ItemTemplate> 



"rp" runat="server"> 



<div style="border:lpx dotted gray; background-color: #f0f0f0; margin: 5px;"> 
<pxstrongxa href="<%#DataBinder.Eval(Container.DataItem / "link") 
%>"><%#DataBinder.Eval(Container.DataItem, "title")%></a></strongxbr /> 



<%#DataBinder.Eval(Container.DataItem / "pubDate")%> - 

<%#DataBinder.Eval(Container.DataItem, "creator")%> 
</p> 



<px%#DataBinder.Eval(Container.DataItem / "description")%x/p> 
</div> 



</ItemTemplate> 



</ASP:repeater> 



H Viene definito un controllo di titpo Repeater associato all'oggetto 
rp. Questo controllo mostrerà il contenuto dei campi 
"lmk","pubDate","title" e "creator". 



ItemDataBound: scatenato quando viene effet- 
tuata l'associazione dei dati su ogni singolo 
item; 

ItemCommand: scatenato quando un control 
contenuto in un item richiede l'esecuzione di un 
comando, in genere associato alle funzionalità 
di modifica o cancellazione. 



, . in - "Italia, corri bok Bit 



il I i I I il. i. - III i 'I 



jASP to ASP.NET Migration Roadshowin 11 città 

Ubi, 03 Mar 20C uele Bochicchio 



ti n altro appuntamento grattato ola non. perdere. Microsoft Italia organizzerà un roacìshow dedicato siila no 
ili 12 date differenti, clic i i ji 



#674 - Effettuare il postback su un'altra pagina con ASP.NET 2.0 

Fri, 04 Feb 200f -, Mostarda 



Una delie novità tetro dotte da - i f 1 2.0 è la possibilità di effettuare A post 1. una pagina vt 
accedere, i i t. reggette ... 



#673 - Client CaUEack con ASP.NET 2.0 

■Thu, 03 Feb 2005 00:00:00 +0100 - Massimo Cappelles 



di ASP.NET 2. 
todice Javascript (. 



introdotte molte nuone fi. maona! ita, tra le quali il Client '-li - : 



■Settimana speciale dedicata ad ASP.NET 2.0 per i 5 a 

•Ibi, 03 Feb 200 ìele Bochicchio 



i di uno s cripti e 



ÌJ\A 'il Gennaio al 04 Febbraio. Era il t; febbraio lr.000 quando il primo storico ir 
oggi, ha ivi fonnat 'differente ... 



Fig. 3: Una tabella può essere formattata usando dei 
template 

I controls condividono anche l'associazione dei dati, 
poiché ognuno di questi è infatti a suo volta compo- 
sto da un numero di controls identificati dal suffisso 
Items presente nel nome. Per il DataGrid abbiamo la 
collezione DataGridltems, per il DataList DataList- 
Items e per il Repeater Repeaterltems. Quando asso- 
ciamo al control la fonte dati, usando la proprietà 
DataSource, ed effettiamo il binding con il metodo 
DataBindQ, viene enumerata la collection con i dati, 
attraverso un ciclo su ogni elemento che quest'ulti- 
ma contiene. Nel caso di un DataSet, viene fatto un 
ciclo sulla collezione Rows contenuta nel DataTable 
di default, al cui interno ha una serie di instanze di 
DataRow, che altro non sono che riferimenti ad un 
record estratto dal database. Quindi, per ogni Da- 
taRow è creato un Repeaterltem (nel caso di un Re- 
peater) o un DataGridltem (nel caso di un DataGrid) 
e viene invocato l'evento ItemCreated, associando la 
DataRow alla proprietà Dataltem del Repeaterltem. 
Viene quindi invocato l'evento ItemDataBound ed il 
ciclo continua con le righe successive, fino all'esau- 
rimento dei dati contenuti nella collection. 



COME PERSONALIZZARE 
L'OUTPUT I TEMPLATE 

Per personalizzare l'output associato ad un control, 
come già detto, si sfruttano i template. In realtà c'è 
un Data Control, tra tutti, in grado di estrarre i dati 




► 92 /Aprile 2005 



ASP.NET 



T CORSI BASE 



senza specificare nessun template, ed è il DataGrid. 
Per tutti gli altri, invece, è necessario specificare al- 
meno un template ed in modo specifico almeno 
l' ItemTemplate. Un template non è altro che un con- 
trol che al proprio interno può contenerne di altri ed 
i tipi supportati dai Data Controls, il cui nome ne 
ricorda le funzionalità, sono: 

• AlternatingltemTemplate 

• ItemTemplate 

• HeaderTemplate 

• FooterTemplate 

• SeparatorTemplate 

In più il DataGrid ed il DataList supportano anche 
EditltemTemplate, che è specifico invece per uno 
stato particolare in cui questi due control si possono 
trovare, ovvero quello di modifca. Mentre nel Data- 
Grid, ancora una volta, questa funzionalità è giù pre- 
sente e si implementa con poche righe di codice, nel 
DataList è necessario costruire manualmente il tem- 
plate, con tanto di controlli input o TextBox, a secon- 
da delle presenze. Il DataList, rispetto agli altri, ha la 
possibilità di incolonnare in maniera differente i 
record, attraverso la proprietà RepeatLayout. 
Consente di specificare, se RepeatDirection è su Ver- 
tical e RepeatColumns su 1 (i valori di default) la mo- 
dalità di rendering del DataList. Di default questo va- 
lore è su Table, che è poi il motivo per cui viene crea- 
ta una tabella con i dati estratti dalla fonte, mentre è 
possibile impostare questo valore su Flow ed utiliz- 
zare un <br /> quale separatore tra ogni record. La- 
vorando su RepeaterDirection e RepeatColumns, in- 
vece, è possibile disporre (in verticale o orizzontale) 
gli items in modo tale che non siano ripetuti uno per 
riga, ma ce ne siano tanti quanti il valore dell'ultima 
proprietà appena menzionata. 
Al pari degli altri controls di ASRNET, è possibile per- 
sonalizzare lo stile associato ad ogni template sfrut- 
tando le rispettive proprietà ItemStyle, EditltemStyle, 
etc, che sono tutte di tipo TableStyle e quindi facil- 
mente personalizzabili. 



QUALE USARE? 

La risposta è semplice. Se avete bisogno di un con- 
trollo completo sull'output, di sicuro il Repeater è 
quello che fa per voi. Nel caso di design table-less o 
con codice XHTML, è l'unico in grado di rendere 
possibile questi due scenari. D'altra parte richiede 
che le funzionalità aggiuntive (paginazione, ordina- 
mento, etc) vengano implementate manualmente. 
Il DataList trova applicazione in quei casi in cui le 
funzionalità avanzate del DataGrid non servono o 
sono eccessive, oltre che nel caso in cui si vogliano 
piazzare più items per riga. Infine il DataGrid an- 
drebbe usato, considerando il codice che produce e 



l'occupazione di ViewState, solo in intranet o co- 
munque in ambienti ad accesso limitato. 





Fig. 4: Nei prossimi articoli vedremo come usare la 
stessa tecnica anche per inserire i dati 



CONCLUSIONI 

Quale che sia il database 
che andrete ad utilizzare, 
le regole esposte in questo 
articolo restano le stesse. I 
Data Controls sono uno 
tra gli argomenti più este- 
si che ASRNET ci consen- 
te di esplorare, poiché le 
personalizzazioni che si 
possono raggiungere so- 
no davvero tante e tali da 
consertirci di adattare 
questi controls a tutte le 
nostre necessità. Ma que- 
sta è un'altra storia e l'ap- 
puntamento per parlarne 
è al prossimo numero! 

Daniele Bochicchio 



LETTURA DI XML 
CON IL DATASET 



<%@ Import Namespace="System.Data" %> 

<%@ Import Namespace= 

"System.Data.SqlClient" %> 

<SCRIPT language="C#" runat="server"> 
void Page_Load (Object sender, EventArgs e) { 

// creo il dataset 

DataSet ds= new DataSetQ; 

// leggo i dati dal file XML 

ds.ReadXml(Server.MapPath("feed.xml")); 

// estraggo tutti i nodi di nome item 



dg.DataSource : 



new DataView( 
ds.Tables["item"]); 



dg.DataBindQ; 



} 



</SCRIPT> 



<ASP: DataGrid id="dg" runat="server"/> 



COS'È UN DATA MANAGER PROVIDER 



ADO.NET è un insieme 
di classi incluse nel na- 
mespace System .Data 
e che si basa sul con- 
cetto di managed pro- 
vider, laddove ADO in- 
vece è basato sulle 
tecnologie OLE-db o 
ODBC. Un managed 
provider non è altro 
che un insieme di 
classi pensate in 
maniera specifica per 
una fonte dati, nel 
caso specifico per un 
database. Ogni mana- 
ged provider è compo- 
sto da un numero di 
classi che sono imple- 



mentate a partire 
dalle interfacce 
contenute nel 
namespace System- 
.Data. Common e che 
garantiscono, per que- 
sto, un'uniformità di 
accesso ai dati sfrut- 
tando namespace dif- 
ferenti. All'interno del 
.NET Framework 1.1 ci 
sono managed pro- 
vider specifici per SQL 
Server, Oracle ed 
ODBC. Chiaramente il 
vantaggio di avere 
managed provider 
dedicati è quello che 
ASP.NET riesce a dia- 



logare in maniera più 
vantaggiosa con i 
database, perché il co- 
dice è ottimizzato e 
pensato per uno speci- 
fico motore. Ad esem- 
pio nel caso di Sql Ser- 
ver anziché usare OLE- 
db, ADO.NET mette a 
disposizione un mana- 
ged provider specifico, 
che lavora attraverso i 
Tabular Data Services 
(TDS). Esistono poi 
managed provider di 
terze parti per MySQL, 
PostGre SQL ed 
addirittura uno per il 
protocollo NTTP! 



Aprile 2005/ 93 ► 





CORSI BASE T 



I 



Macromedia Flash Action Script 2.0 




Flash: all'interno della programmazione ad oggetti 

Ereditarietà 
in ActionScript 

Impariamo i principi base della programmazione ad oggetti, come 
estendere le classi di Action Script e facciamo qualche esempio d'uso 
molto utile 




Utilizza questo spazio per 
le tue annotazioni 




MéMMUMMUJUm 

131 ActionScript 1.0 
~y ed una discreta 
padronanza 
ne II 'utilizzo di Flash 
Mx e ActionScript 2.0. 



Flash Mx 2004 
Porfessional 



Tempo di realizzazione 



Una classe è un modello per la creazione di 
oggetti tali che abbiano in comune tutte le 
proprietà e i metodi in essa definiti. I meto- 
di sono azioni compiute da un'istanza della classe. 
Le proprietà sono variabili definite in una classe di 
oggetti in cui si memorizzano dati di un determina- 
to tipo. L'ereditarietà è la tecnica utilizzata per orga- 
nizzare classi di oggetti secondo una precisa gerar- 
chia dove una classe, generalmente indicata come 
classe figlia, può ereditare tutti i metodi e la proprie- 
tà di un'altra detta classe padre. Nella programma- 
zione orientata agli oggetti con i termini interfaccia 
e implementazione si opera una distinzione tra cosa 
ci si deve aspettare dall'esecuzione di un metodo e 
come si è operato per implementarlo. 



EREDITARIETÀ 
E INTERFACCE 

Nel paradigma di programmazione orientato agli 
oggetti con il termine ereditarietà si intende una re- 
lazione formale fra due o più classi di oggetti dove la 
sotto classe eredita, dalla classe padre, le proprietà e 
i metodi in essa definiti. Dal punto di vista mera- 
mente pratico l'ereditarietà tra classi fa si che una 
classe possa utilizzare il codice, quindi i metodi e le 
proprietà, appartenente ad un'altra classe. Concet- 
tualmente però si va ben oltre, infatti, attraverso l'e- 
reditarietà, si riesce a stabilire una vera e propria 
scala gerarchica tra differenti classi organizzate in 
gruppi. Partiamo da un semplice esempio (inheri- 
tance.fla) e da due classi definite in due documenti 
.as esterni (Father.as e Daughter.as) e vediamo come 
sia immediato fare ereditare alla classe Daughter i 
metodi e le proprietà della classe Father. Definiamo 
nella prima classe il costruttore e un metodo che 
esegue semplicemente un trace 

class Father { 



function Father(){> 



public function testMethod(){ 



trace("Ciao dalla classe Father!");} 



> 



La keyword da utilizzare per stabilire la relazione tra 
due classi è extends e va inserita subito dopo la di- 
chiarazione del nome della classe, quindi, per crea- 
re una classe "figlia" che eredita tutti i metodi della 
classe "padre", usiamo questa sintassi 

class Daughter extends Father{ 

function Daughter(){> 

public function testMethodDaughter(){ 

trace("Ciao dalla classe Daughter!");} 



Apriamo il nostro .fla e, nel pannello delle azioni, 
scriviamo il codice necessario per creare una nuova 
istanza della classe Daughter e richiamiamo il meto- 
do testMethodQ 

var a = new Daughter (); 
a.testMethod(); 

Quando si invoca un metodo non presente nella 
classe il compilatore, prima di generare un errore 
dovuto alla mancanza del metodo, va a cercare il 
metodo nella classe con la quale è stata stabilita l'e- 
reditarietà. Tutte le applicazioni sviluppate seguen- 
do il paradigma della programmazione Object- 
Oriented possono essere viste come un diagramma 
formato da diverse classi legate fra loro da vincoli di 
ereditarietà. Nelle prime lezioni di questa guida ab- 
biamo parlato dei tipi di dati ammissibili in Flash e, 
tra le novità della versione 2004, abbiamo evidenzia- 
to che ogni classe, anche quelle che abbiamo defini- 
to noi direttamente, è un data type valido. Quando 
definiamo un vincolo di ereditarietà tra due classi, la 
classe figlia viene considerata come un "sotto tipo" 




► 94 /Aprile 2005 



Macromedia Flash Action Script 2.0 



T CORSI BASE 



della classe padre. Per questo motivo, tipizzando la 
variabile in cui memorizziamo la nuova istanza 
creata, non otteniamo errori 

var aTyped:Father = new Daughter (); 

Un altro aspetto molto interessante dell'ereditarietà 
tra classi è che, oltre a poter ereditare metodi e pro- 
prietà nella classe figlia, è possibile sfruttare questa 
ultima per definire delle nuove versioni dei metodi 
della classe padre eseguendo la cosiddetta sovra 
scrittura del metodo. Per creare una nuova versione 
del metodo testMethodQ nella classe figlia è suffi- 
ciente aggiungere questo membro alla classe defi- 
nendo le nuove operazioni da svolgere. Provate a to- 
gliere i commenti inseriti nella classe Daughter e ad 
eseguire di nuovo il codice, come sempre un esem- 
pio vale più di mille parole! 



INTERFACCE 

Un'interfaccia, in ActionScript 2.0, è un costrutto 
utilizzato per fornire una definizione di un nuovo 
tipo di dato. Può sembrare superfluo utilizzare 
un'interfaccia visto che, come abbiamo detto, già 
una classe definisce un nuovo tipo di dato. La diffe- 
renza sostanziale è che un classe definisce il dataty- 
pe e le implementazioni dei suoi metodi e delle sue 
proprietà, un'interfaccia lo definisce invece solo in 
termini astratti senza occuparsi delle implementa- 
zioni. In un'interfaccia vengono dichiarati tutti i 
metodi che devono essere necessariamente definiti 
nelle classi che la implementano ed è per questo che 
la si può definire come uno strumento per descrive- 
re gli scopi per i quali viene implementata una clas- 
se. La distinzione tra implementazione del codice e 
descrizione dei compiti per cui è preposta una clas- 
se aiuta a mantenere più comprensibile il design 
dell'applicazione e di tutti i suoi componenti. 
Utilizziamo sempre lo stesso .ila e vediamo come 
definire un'interfaccia ed impostare un classe in 
modo tale che questa venga implementata al suo 
interno. Per definire un'interfaccia è necessario 
creare un nuovo file .as esterno (Testlnter .as) che, 
pur rispettando le stesse regole di un file contenen- 
te una classe, invece della keyword class, inizi con la 
keyword interface 

interface TestInter{function method():Void;> 

Al suo interno troviamo solo la dichiarazione dei 
membri che una classe che implementa l'interfaccia 
deve necessariamente definire e il tipo di dati che 
deve essere restituito dal metodo. La keyword imple- 
ments permette di specificare l'interfaccia che una 
classe implementa, se aprite la classe InterfaceUsed- 
.as tutto sarà più chiaro 




class InterfaceUsed implements Testlnter{ 

function InterfaceUsed(){> 

public function method():Void{ 
trace("test!");> 

} 



Se nella classe non fosse definito il metodo \ 
il compilatore di Flash genererebbe un messaggio di 
errore. Gli stessi meccanismi utilizzati per stabilire 
l'ereditarietà fra due classi possono essere applicati 
alle interfacce. 



ESTENDERE LE CLASSI 
ESISTENTI 

Una delle classi più utilizzate in Flash è sicuramente 
la classe MovieClip. Abbiamo già discusso a lungo 
sull'importanza e le potenzialità dei clip filmato 
all'interno di un progetto sviluppato in Flash; ve- 
diamo ora, partendo proprio da questa classe, quan- 
to sia facile e utile estendere con ActionScript 2.0 le 
classi built-in di Flash. Aprite un nuovo .fla 
{extendsMovieClip.fla) e vediamo come sia possibile 
aggiungere dei metodi alla classe MovieClip per fare 
in modo che questa possa muoversi via codice sullo 
stage. Creiamo un nuovo file Mover.as e dichiariamo 
una classe che estenda i clip filmato 

class Mover extends MovieClip{ 

A questo punto, ragionando sulle funzionalità che 
questa classe dovrà avere, appare evidente che è ne- 
cessario implementare un metodo pubblico che ge- 
stisca lo spostamento e tre proprietà in cui memo- 
rizziamo la velocità del movimento (public) e le 
coordinate del punto che il nostro clip filmato deve 
raggiungere (private) 

private var toX:Number; 
private var toY:Number; 
public var speed:Number; 

Ora, dopo aver definito il costruttore che assegnerà 
il valore 3 alla proprietà speed, implementiamo il 
metodo ìììMÌ 



function Mover(){speed = 3;} 


public function moveToPoint(x:Number 


y:Number):Void{^ 


toX = x; 


toY = y; 


this.onEnterFrame = function(){ 


_x += (toX - _x) / speed; 


_y += (toY - _y) / speed; 


if (Math.abs (toX - _x) < 0.2 && Math.abs ( 

toY - _y) < 


0.2) { 


_x = toX; 


_y = toY; 




TOOLS 
CONSIGLIATI 

SePy 

www.sephiroth.it 

SciteFlash 

http://www.bomberstudios 
■com/sciteflash/ 

JEdit 

http://www.jedit.org/ 

Eclipse 

www.eclipse.org 

XCode 

http://blog.pixelconsumption 
.com/files/Actionscript 
Xcode tutorial.rtf 



Aprile 2005/ 95 ► 





CORSI BASE T 



I 



Macromedia Flash Action Script 2.0 





this.onEnterFrame = undefined;} } 



} 




www.actionscript.it 

www.risorseflash.it 

www.ingenium.ws 

h tt p ://www. d of a et o ry. co m/ 

Patterns/Patterns.aspx 

http://www.csc.calpoly.edu 

/-dbutler/tutorials/ 

winter96/patterns/ 



Il vantaggio derivante dall' estendere la classe Movie- 
Clip appare quanto mai evidente dall'implementa- 
zione del metodo che sfrutta sia le proprietà _xej 
del clip filmato, sia l'evento onEnterFrame che tutti 
noi siamo abituati ad usare. 

Torniamo al nostro .fla e vediamo come utilizzare 
questa classe al suo interno. Create un nuovo clip fil- 
mato contenente un cerchio, assegnategli un linka- 
ge e popolate il campo AS2 Class con il nome della 
classe che volete associare al clip filmato (Mover) 
senza l'estensione .as. 

Aprite il pannello delle azioni e, dopo aver posizio- 
nato via codice una nuova istanza del clip filmato, 
chiamate il metodo moveToPointO indicando le 
coordinate del punto che il clip filmato deve rag- 
giungere 

this.attachMovie("ball", "ball_mc", 0); 
ball_mc.moveToPoint(300, 400); 

Il risultato ottenuto è quello di un movimento iner- 
ziale del vostro clip filmato ed è interamente gestito 
da un file esterno quindi, ogni qual volta decidiate di 
apportare modifiche al codice, sarà sufficiente met- 
tere mano al file .as esterno. 



COSTRUTTORI 

La programmazione ad oggetti in ActionScript 2.0 
e la definizione di classi esterne è una delle novità 
più rilevanti introdotte in Flash Mx 2004. Abbiamo 
già parlato del costruttore di una classe definen- 
dolo come quella funzione che viene automatica- 



mente richiamata dall'operatore new e che ci per- 
mette di eseguire delle operazioni preliminari 
sulle nuove istanze di una classe. Il costruttore 
deve avere lo stesso nome della classe e non può 
specificare nessun tipo di valore che venga resti- 
tuito dopo la sua esecuzione. L'istruzione return 
può essere quindi utilizzata solo per interrompere 
l'esecuzione della funzione ma non per altri scopi. 
Un costruttore può essere dichiarato come public 
o come private, ma mai come membro static della 
classe. 
Utilizzando una dichiarazione del tipo 

class Test{ 

private function Test(){ 

_J 



} 



definiamo una classe le cui istanze non possono 
essere create direttamente e per questo dovremo 
definire un metodo della classe che ci consenta di 
creare nuove istanze. 

L'utilizzo di questo approccio è necessario quando 
vogliamo simulare la definizione di classi abstract 
in pieno stile Java che non devono essere istanzia- 
te ma solo estese o per limitare il numero di istan- 
ze create quando la nostra applicazione è in ese- 
cuzione. 

Un limite dei costruttori in ActionScript 2.0 è la 
mancanza di supporto per i costruttori multipli, 
ovvero di diverse funzioni che vengano eseguite in 
base al numero di argomenti passati in fase di 
istanziazione. 

Per superare questa mancanza è possibile struttu- 
rare il costruttore della classe in modo tale che 
richiami diversi metodi private in base agli argo- 
menti: 



UTILIZZARE COSTRUTTORI E DISTRUTTORI 



PREPARIAMO IL FLA 














i A 

' -. 

y ,/ 

t> <• 

a o. 


"*"«»»«" " ose 










g— i 






a*« 




« a ras "i 


-aal < - 


- i 


J" ° B 


~. i 


















* 






t= 


(M ^ 




"=*■—! % 












h, nu * i«.3 









D Apriamo un nuovo fla. Nella 
timeline principale aggiungiamo 
due livelli uno per le azioni e uno 
contenente un campo di testo dinamico 
con nome resultjtxt in cui visualizzeremo 
i risultati delle operazioni. 



DEFINIAMO LA CLASSE CONSTRUCTOR 


MSis^^^ 




Type: 






Description: 


£] Fls:-.h [■.:..:ur,wr.f 

Q FI ash riide Fi eserrt àdon 

£) Flash Form Application 




— ■ ■ :.-'■: 
e* it in the Sci'T t wir.djw. AdbnScript is the Flash 

n vi^ ■• arn; : '■;' ■.:■ Voj - -. ::. ■ :.. :■ . 
■".>:■: .':.:..::■ lìeìp 
ernal : 


L:|ESSJS5HB1I 


HJi ActionScript ■..niniuni.ah.n File 
% Flash JavaScript File 
Flash Project 




class 


Constructor{ 


public var result; 


} 



H Definiamo ora la nostra classe in 
un file .as esterno ricordandoci che 
il nome del file deve essere identico al 
nome della classe. Per creare il file .as 
possiamo usare un qualunque editor di 
testo, oppure l'editor integrato in Flash 



DICHIARIAMOLO COME PRIVATE 



private function Constructor(a:Number, 

b:Number){ 

if( a != undefined && b != undefined){ 



newTwoArguments(a,b); 



> 



if(arguments.length == 0){ 



newWithoutArguments(); 



> 



Il costruttore della nostra classe 
sarà un membro private della 
classe e la funzione che lo definisce 
richiamerà due metodi differenti in base 
agli argomenti passati in fase di 
istanziazione 




^ 96 /Aprile 2005 




Macromedia Flash Action Script 2.0 



i 



T CORSI BASE 




class Test{ 


private function Test(a 


Number, 


b:N 


umner){ 


if(arguments.length 


> 0){ ... 






} 


} 
} 



per quanto il nostro articolo possa essere sembrato 



teorico, era importante introdurre i concetti che 
stanno alla base dell' ereditarietà delle classi. 
Alcune cose potrebbero esservi sembrate astratte 
nello scorrere del discorso, e tuttavia se avrete la pa- 
zienza di sperimentare in pratica quanto abbiamo 
esposto, sicuramente ne ricaverete vantaggi inim- 
maginabili. 

Giorgio Natii i 




CHE COS'È UM DESIGN PATTERN 



Quando in fase di sviluppo ci 
scontriamo con una 
problematica da risolvere, 
presumibilmente ciò che 
abbiamo riscontrato, o un 
problema molto simile ad esso 
con più di una caratteristica in 
comune, è stato già risolto da 
altri sviluppatori in situazioni 
analoghe o molto simili alla 
nostra. Un Pattern altro non è 
se non una formalizzazione di 
un modello che descrive 
dettagliatamente una soluzione 
ad uno specifico problema. 
I Design Patterns sono un 
strumento che mette in 
evidenza le caratteristiche 
essenziali che un'applicazione 
deve avere per risolvere un 
particolare problema 
astraendosi dal linguaggio 
utilizzato e focalizzando 
piuttosto l'attenzione sulle 
classi che devono essere 
implementate. 

Nel corso del tempo sono stati 
definiti diversi Design Pattern e 
parallelamente si è sviluppato 



ed evoluto un formato che 
viene formalmente indicato 
come quello da seguire per 
descrivere un Design 
Pattern.Ogni Design Pattern 
deve essere descritto fornendo 
un nome, una breve descrizione 
del problema che affronta, i 
requisiti necessari per la sua 
implementazione, la soluzione 
da adattare, le motivazioni 
plausibili per non scegliere di 
utilizzarlo e gli altri eventuali 
Patterns utilizzati al suo 
interno. 

Model View Control (MVC) è 
uno dei Design Patterns più 
utilizzati. 

Il modello (Model) è 
l'applicazione vera e propria, la 
vista (View) è la 
rappresentazione a video 
dell'applicazione stessa, il 
controllore (Controller) si 
occupa di sincronizzarli facendo 
in modo che gli input 
dell'utente vengano trasmessi 
da View a Model che a sua 
volta modificherà l'aspetto 



dell'applicazione in base alle 
operazioni eseguite. 
MVC fondamentalmente scinde 
"aspetto" e "core" di una 
applicazione stabilendo fra loro 
una relazione di 
interdipendenza basata su una 
comunicazione tra istanze di 
oggetti. L'interfaccia grafica 
dell'applicazione gestita dalla 
classe View deve essere in 
grado di rispecchiare tutti i 
cambiamenti che avvengono 
nel modello in base ai 
cambiamenti dei dati in esso 
memorizzati. 

Una caratteristica peculiare di 
questo Design Pattern, che poi 
altro non è altro se non uno dei 
principi della programmazione 
Orientata agli Oggetti, è la 
possibilità di gestire più "viste" 
simultaneamente anche 
nidificate tra loro. 
Si intuisce che l'ereditarietà 
delle classi di cui abbiamo 
parlato in questo articolo, ì 
fondamentale per applicare la 
teoria dei design patterns. 



BIBLIOGRAFIA 



• ACTIONSCRIPT THE 
DEFINITVE GUIDE FOR 
FLASH MX 

Colin Moock 

• ACTIONSCRIPT 2.0 
ESSENTIALS 

Colin Moock 

• OBJECT-ORIENTED 
PROGRAMMING WITH 
ACTIONSCRIPT 2.0 
Jeff Tapper 

• AN INTRODUCTION TO 
OBJECT ORIENTED 
Programmino 
Timothy Bud 





DEFINIAMO UN METODO STATIC 




DEFINIAMO 1 METODI 




UTILIZZIAMO LA CLASSE DEFINITA 






public static function getNewIstance( 

a: Number, b: Number) :Constructor{ 
return new Constructor(a,b); 




private function newTwoArguments( 

a:Number, b:Number):Void{ 
result = arguments; 
} 
private function newWithoutArguments( 

):Void{ 
result = "No arguments"; 
} 




var a = Constructor.getNewIstance(2,3); 
result txt.text = a. result; 




} 




wm Per creare nuove istanze della 
mM classe dovremo definire un metodo 
static, ovvero un metodo che 
richiameremo senza dover prima creare 
nuove istanze della classe. Questo 
metodo sarà richiamato direttamente 




|9 Definiamo due metodi private che 
IsM vengono richiamati dal costruttore 
e che utilizzeremo per popolare la 
proprietà result precedentemente 
definita. Questi due metodi non fanno 
altro che scrivere una stringa 


1 
i 


WM In Flash non faremo altro 
LI richiamare il metodo 
getNewlstance e popolare il campo di 
testo result_txt con il valore 
memorizzato nella proprietà result. 
Abbastanza semplice. 





Aprile 2005/ 97 ► 




Visual Basic .NET 



T CORSI BASE 



Procedure e Funzioni in Visual Basic .Net 

Come frazionare 
un programma 

In questo articolo analizzeremo le procedure, le piccole unità logiche 
di codice che, unite, formano un'applicazione più ampia 
Questo modo di procedere è uno standard in programmazione 



Una procedura (chiamata genericamente 
routine o sottoprogramma) è una parte di 
programma che può essere richiamata da 
un punto qualsiasi del codice. Il salto ad una proce- 
dura, si verifica tramite l'invocazione del nome della 
procedura stessa. Al termine della procedura il con- 
trollo torna al programma chiamante e l'esecuzione 
prosegue con l'istruzione successiva a quella che ha 
eseguito la chiamata. Le routine possono essere uti- 
lizzate per riunire in un unica porzione di codice 
operazioni ripetute e condivise (ad es. per calcoli 
utilizzati frequentemente). 



LE ROUTINE DI VB.NET 

In VB.Net si possono usare diversi tipi di routine: 

• Le routine Sub (procedure). Una routine Sub è 
composta da una porzione di codice racchiusa 
tra un'istruzione Sub ed un'istruzione End Sub. 
Ogni volta che la routine viene chiamata, vengo- 
no eseguite le relative istruzioni a partire dall'i- 
struzione successiva alla parola chiave Sub fino 
alla parola chiave End Sub (è possibile uscire da 
qualsiasi punto della procedura con le istruzioni 
Exit Sub o Return). Una routine Sub esegue ope- 
razioni ma non restituisce alcun valore. 

• Le routine di gestione degli eventi. Le routine di 
gestione degli eventi sono routine Sub che ven- 
gono eseguite in risposta ad un evento generato 
da una azione dell'utente (ad es. il click del mou- 
se su un bottone). 

• Le routine Function (funzione). Una routine 
Function è simile ad una routine Sub, con la dif- 
ferenza che restituisce un valore al codice chia- 
mante. 

• Le routine Property, note anche come funzioni 
di accesso alle proprietà, consentono di gestire i 



valori delle proprietà di oggetti o moduli. Saran- 
no analizzate in dettaglio nei prossimi articoli 
quando presenteremo la programmazione ad 
oggetti. 



CREAZIONE 

DI UNA PROCEDURA 

Per creare una procedura è sufficiente digitare l'inte- 
stazione della procedura nella finestra del codice e 
premere INVIO. L'intestazione di una routine può 
essere rappresentata semplicemente dalla parola 
chiave Sub (o Function) seguita da una stringa che 
ne rappresenti il nome. 
Per esempio, possiamo scrivere 

Sub Prima Procedura 

e premere INVIO, a questo punto VB riconoscerà il 
codice come una nuova procedura, e ne completerà 
il modello scrivendo automaticamente: 

Sub Prima Procedura () 

End Sub 

La sintassi, in forma ridotta, di una procedura è la 
seguente: 

[{Public | Protected | Friend | Protected Friend | 

Private }] Sub nomeprocedura (argomenti) 

istruzioni 
End Sub 

L'uso di una delle parole chiave (facoltative), prima 
dell'istruzione Sub determina l'area di visibilità di 
una procedura. In particolare una procedura dichia- 
rata con la parola chiave Private può essere chiama- 
ta solo all'interno della classe, del modulo o della 




Utilizza questo spazio per 
le tue annotazioni 



jn 




REQUISITI 



hil nessuna 



Sistema 

operativo: Windows 
2000/XP. Visual Basic 
.NET 2003 



Tempo di realizzazione 



v -/ 



Aprile 2005/ 99 ► 





CORSI BASE T 



I 



Visual Basic .NET 





form in cui viene definita, mentre una procedura 
dichiarata con la parola chiave Public è accessibile 
da qualsiasi parte del codice. Per default una routine 
è sempre Public perciò in questo caso è possibile 
omettere tale attributo, in caso contrario è sempre 
necessario dichiarare la visibilità di una routine con 
la parola chiave Private. Tutte le routine di gestione 
degli eventi sono invece Private. Le altre possibilità 
saranno più chiare quando introdurremo la pro- 
grammazione ad oggetti. Come argomenti è possi- 
bile specificare un elenco di variabili (contenenti 



dati dell'applicazione) utilizzabili dal codice interno 
alla procedura. L'uso degli argomenti non è obbliga- 
torio, ma se sono presenti, devono essere separati da 
una virgola e devono essere racchiusi tra parentesi. 



LE FUNZIONI 

Così come le procedure, le funzioni sono sottopro- 
grammi (routine) che possono ricevere e modificare 
argomenti e possono eseguire operazioni ripetute e 



L'istruzione Exit Sub 

consente di uscire 

immediatamente da 

una procedura. Per 

uscire da una funzione 

l'istruzione diventa 

Exit Function. 

L'esecuzione 

dell'applicazione 

continuerà con 

l'istruzione 

immediatamente 

successiva 

all'istruzione che ha 

richiamato la 

procedura o la 

funzione. In una 

procedura o funzione è 

possibile inserire 

qualsiasi numero di 

istruzioni Exit Sub o 

Exit Function. Anche 

l'istruzione Return 

consente di uscire 

subito dalla routine 

ottenendo lo stesso 

effetto di Exit Sub. È 

possibile inserire un 

numero illimitato di 

istruzioni Return in 

qualsiasi punto di una 

routine, nonché 

combinare istruzioni 

Exit Sub e Return. 



CALCOLA AREA 

Mettiamo subito in azione le 
routine creando un nuovo 
progetto Windows Applications 
dal nome Calcola Area. 



L'applicazione che andremo a 
realizzare, dovrà semplicemen- 
te calcolare l'area di un 
triangolo con le dimensioni di 



base ed altezza inserite 
dall'utente. La prima fase è 
quella del disegno 
dell'interfaccia utente. 




O Selezioniamo la finestra Formi e, se 
non è già visualizzata, apriamo la 
finestra delle proprietà. 
Dalla finestra delle proprietà selezioniamo la 
proprietà Name e cambiamo subito il nome 
in: Form Area. 

Selezioniamo la proprietà Text e modifichia- 
mo il testo visualizzato nella barra del titolo 
in: Calcolo dell'area di un Triangolo. 



W - fél - & & 5» ► Debug . & 

^ IJ-JLI.J.IH,.I..L..1«'l 

I 



J^ 



ab] Butta 
libi TextEox 



□ Croi 

□ Pan, 



H Selezioniamo per tre volte un controllo 
TextBox dalla casella degli strumenti 
(nella sezione Windows Form) e disegniamo i 
tre controlli sulla form. 



gl'fel'G^HfllJt^fe^'^'P'lit ► Debug T-& 

a 1 1° £ m\w * bb* | Fg o °:d e§3 | «° g? k a 1 1 & §; e: | m e 




;^^ 



; |TextBox3 



Selezioniamo il primo Textboxe, dalla fine- 
stra delle proprietà, evidenziamo la proprie- 
tà Name per cambiare il nome in: TextBoxBase. 
Evidenziamo la proprietà Text e cambiamo il testo 
nella stringa vuota. Allo stesso modo: selezionia- 
mo il secondo TextBox e variamo la proprietà Na- 
me in: TextBoxAltezza e la proprietà Text a vuoto; 
selezioniamo il terzo TextBox e variamo la pro- 
prietà Name in: TextBoxArea e Text a vuoto. 



^fammsmmm 

- e Voci fica Visualizza 


B-'oce;;: 


Ge'^e'a 3ei~-c --'-L- 


Strumenti Finestra 




s-i^yi 


} uni | S O £D 83 1 «- 55 


>. Debug 


\$ 


t 1= £ =1 fi 4 


!R ffi | | £1 & ei 


- 

i 


Dati 










Corsoceli 






Windows Form 


1- 




La beli 


1^ Puntatore 


| A Label 


:l 

p ■ d d 

□ Label2 a 
■ □ □ a 


A LinkLabel 
abj Button 
labi TextEox 
§ MainMenu 
p CheckBox 
t? RadioButton 
[ 1 GroupBox 
^ PictureBox 
□ Panel 
§3 DataGrid 
H ListEox 
IH CheckedListBox 
|S ConnboBox 










I 





























□ Selezioniamo per tre volte un controllo La- 
bel dalla casella degli strumenti e disegnia- 
mo i tre controlli sulla form in corrispondenza dei 
tre TextBox disegnati in precedenza. 




► 100 /Aprile 2005 




Visual Basic .NET 



i 



T CORSI BASE 




condivise. A differenza delle procedure, le funzioni 
possono restituire un singolo valore che può essere 
assegnato ad una variabile, oppure può essere utiliz- 
zato all'interno di un'espressione. 
La sintassi, in forma ridotta, di una routine Function 
è la seguente: 

[{Public | Protected | Friend | Protected Friend | 

Private }] Function nomefunzione (argomenti) [As tipo] 
istruzioni 
End Function 



S-a-eys * i 



• ^B • H | ► Debug - ^ 



H Selezioniamo la prima Label e, dalla 
finestra delle proprietà, evidenziamo la 
proprietà Text per cambiare il testo visualizzato 
in: Base. Allo stesso modo: selezioniamo la 
seconda Label e variamo la proprietà Text in: 
Altezza; selezioniamo la terza Label e variamo 
la proprietà Text in: Area. 





"S™™ 


< li» 




■furi ii 


™ E f m ' 1 " rHÌaaÌM— 






tp - fa - & u si 

| ft le è -a \w « 


P: o . o. - P - H | > Debug 

3 O si EE | «° 55 K ffi | § * 


•|# 


- 


Bff «*^*. 


§t et | a HI | 4 % , 






I 

i 


tot llw,l— 




*™.] 








m a\®\&\tà 


A Kfcd 

A UnkLabal 
■ Button 




.^:..::-, -:: :-_-.:;:.■. z ..* : 




1 


" ,M ::::;::.::■ [^ 


Proprie,, 4 X 


B Texfflo» 

1 m*m™ 

" GrcupBox 

H «*"*» 

Q Panel 
,53 DataGrid 
Ei ListBox 

O C™boB„ 

fe Tree „a» 
■ TabConfrol 


1 


fflti IH a 


A. 


■ c™.r iDefeult 


1 


- -,- 






™; :: -' ! r 












• 


iiirr 




«"sto contenuto nel controllo. 



Selezioniamo un controllo Button dalla 
casella degli strumenti e disegniamolo 
sulla form. 



m - y • ^ u *■' 




' B Esplora solrcor.^ 



□ Selezioniamo il controllo Button e, dalla 
finestra delle proprietà, modifichiamo la 
proprietà Name in: ButtonCalcola e la proprietà 
Text in: Calcola Area del Triangolo. 



Le considerazioni sulla visibilità delle funzioni e sul- 
l'uso degli argomenti sono uguali a quelle fatte per le 
procedure. A differenza delle procedure è prevista 
l'istruzione facoltativa As tipo, dove tipo definisce il 
tipo di dati del valore restituito dalla funzione. Affin- 
ché una funzione possa restituire un valore, si deve 
usare al suo interno, una variabile con lo stesso no- 
me della funzione ed assegnargli il valore desiderato, 
oppure includerlo in un'istruzione Return. L'istru- 
zione Return consente, contemporaneamente, di 
assegnare il valore restituito e di uscire dalla funzio- 
ne. Ad esempio le due funzioni seguenti, che resti- 
tuiscono il valore di Pi Greco, hanno lo stesso effetto. 



Public Function PiGreco() As Doublé 


PiGreco = 3.1415 


End Function 


Public Function PiGreco() As Doublé 


Return 3.1415 


end Function 



CHIAMATE DI 
PROCEDURE E FUNZIONI 

Per utilizzare le istruzioni di una determinata proce- 
dura, si deve chiamare quest'ultima per nome, uti- 
lizzando uno dei due possibili metodi. Ad es. per 
chiamare una procedura di nome CalcolaArea: 

• Cali CalcolaAreaO in cui il nome della procedura 
è preceduto dalla parola chiave Cali 

• CalcolaAreaO specificando cioè soltanto il nome 
della procedura 

I due metodi sono equivalenti, ma per la leggibilità 
del codice è importante utilizzare sempre lo stesso 
metodo, qualsiasi sia la vostra scelta (personalmen- 
te evito di scrivere la parola Cali prima del nome 
della procedura). Per chiamare una routine Sub, è 
necessario racchiudere tra parentesi l'eventuale 
elenco di argomenti. Se la procedura non richiede 
argomenti possiamo evitare di scrivere le parentesi 
che saranno, in ogni caso, inserite in automatico da 
VB.Net. Per chiamare una funzione, è necessario 
scrivere il nome della funzione a destra di una qual- 
siasi espressione (è un espressione anche la sempli- 
ce assegnazione di valore ad una variabile) così 
come vengono utilizzate le funzioni intrinseche di 
VB, quali ad es. CDbl(Numero) introdotta nell'arti- 
colo precedente. Per le funzioni vale la stessa regola 
delle procedure: se sono presenti degli argomenti, 
devono essere sempre racchiusi tra parentesi. Si può 
ad esempio scrivere: 

A = AreaRettangolo(b, h) 

If AreaRettangolo(b, h) < Then MessageBox.Show( 

"Errore nell'inserimento dei dati") 




Le variabili dichiarate 
all'interno della routine 
(utilizzando l'istruzione 
Dim o istruzioni equiva- 
lenti) sono sempre va- 
riabili locali alla routine 
e la loro vita coincide 
con la vita della routine 
stessa. 



• Le routine dichiarate 
con la parola chiave Pro- 
tected dispongono di 
accesso protetto e sono 
accessibili solo dalla 
classe corrispondente 
oppure da una classe 
derivata. 

• Le routine dichiarate 
con la parola chiave 
Friend dispongono di 
accesso Friend e sono 
accessibili dall'interno 
del programma che ne 
contiene la dichiarazio- 
ne. Può essere chiamata 
da qualsiasi punto del 
progetto corrente, ma 
non dall'esterno. 

• Le routine dichiarate 
con le parole chiave 
Protected Friend dispon- 
gono di accesso con- 
giunto protetto e Friend 
e possono essere utiliz- 
zate dal codice in classi 
derivate. L'accesso Pro- 
tected Friend può essere 
specificato soltanto per 
membri di classi. 



Aprile 2005/ 101 ► 





CORSI BASE T 



I 



Visual Basic .NET 





In Visual Basic 6 la 

lunghezza dei nomi 

delle procedure era 

limitata da un 

massimo di 40 

caratteri. 



Fate attenzione al 

passaggio dei 

parametri ad una 

procedura, 

specialmente se si 

viene dalla scuola di 

VB6, non 

dimentichiamoci che in 

VB6, al contrario di 

VB.NET i parametri 

sono passati di default 

per riferimento 

(ByRef). 



È inoltre possibile richiamare una funzione con le 
stesse modalità utilizzate per le procedure: 

• Cali AreaRettangolo (b,h) 

• AreaRettangolo (b,h) 

Utilizzando questi metodi però, la chiamata di fun- 
zione non restituisce nessun valore. Nei due TextBox 
d'input {TextBoxBase e TextBoxAltezza), l'utente do- 
vrà inserire i valori della base e dell'altezza del trian- 
golo. Quando l'utente clicca con il mouse sul botto- 
ne, sarà lanciata la procedura di evento ButtonCal- 
cola_Click che mostrerà nel TextBox di Output {Text- 
BoxArea) il risultato dell'operazione. 



LE PROCEDURE DI 
GESTIONE DEGLI EVENTI 

In VB.Net è importante distinguere due tipi di proce- 
dure: 

• Procedure generali 

• Procedure di gestione degli eventi. 

Le procedure generali non sono legate ad alcun 
oggetto dell'interfaccia e, dopo essere state defini- 
te, devono essere richiamate in modo specifico 
dall'applicazione. Le procedure di gestione degli 
eventi appartengono ad una form o ad un control- 
lo e vengono eseguite automaticamente in rispo- 
sta a particolari eventi generati dall'utente (ad 
esempio il clic su un Button) o dal sistema. Nelle 
procedure di gestione di eventi è sempre possibile 
chiamare una procedura generale. Il nome delle 
procedure di gestione degli eventi è costituito dal 
nome effettivo assegnato al controllo nella pro- 
prietà Name, da un carattere di sottolineatura (_) e 
dal nome dell'evento. 

Il nome della procedura associata all'evento clic 
del pulsante ButtonCalcola sarà appunto Button- 
Calcola_Click. 



ATTRIBUIRE I NOMI 
ALLE PROCEDURE 

È possibile attribuire un nome qualsiasi ad una pro- 
cedura, considerando però, i seguenti limiti: 

• Il nome deve iniziare con un carattere alfabetico 
o con un carattere di sottolineatura (_). Se il no- 
me di una procedura inizia con un carattere di 
sottolineatura, è necessario che contenga alme- 
no un carattere alfabetico o una cifra decimale 
(non è possibile chiamare una procedura sem- 
plicemente _). 

• Il nome deve contenere solo caratteri alfabetici, 
cifre decimali o caratteri di sottolineatura. 

• Il nome non deve superare la lunghezza massi- 
ma di 1023 caratteri. 

In VB.Net qualsiasi elemento del programma può 
avere lo stesso nome di una parola chiave riservata, 
a patto di racchiuderla tra parentesi quadre ([ ]). È ad 
esempio possibile creare una procedura denomina- 
ta While: 

Private Sub [WhileJQ 

'righe di codice 

End Sub 

Se nella dichiarazione della procedura non si utiliz- 
zano le parentesi quadre, VB considera l'utilizzo del 
nome While come la corrispondente parola chiave 
generando quindi un errore di compilazione. 
Personalmente vi sconsiglio di utilizzare questa 
opportunità, sia perché è facile dimenticarsi di rac- 
chiudere i nomi riservati tra parentesi quadre, sia 
perché rende più difficile la lettura del codice. Così 
come abbiamo visto per i nomi delle variabili, 
anche per le routine vale la buona norma di utiliz- 
zare dei nomi che descrivono la funzione della pro- 
cedura piuttosto che nomi generici di difficile inter- 
pretazione. È buona norma, inoltre, far precedere la 
routine da un breve commento sulle proprie fun- 
zionalità. 



FINESTRA DEL CODICE 



DICHIARAZIONE DELLE VARIABILI 



INIZIALIZZAZIONE DELLE VARIABILI 



Private Sub ButtonCalcola_Click( 

ByVal sender As System. Object, ByVal e 

As System. EventArgs) Handles 

ButtonCalcola.Click 

End Sub 



nPer scrivere il codice è sufficiente 
fare doppio click sul controllo 
Button. Con questa operazione si aprirà 
la finestra del codice con il cursore 
posto all'interno della procedura di 
evento ButtonCalcola.Click. 



Dim Area As Doublé 


Dim Base As Doublé 


Dim Altezza As Doublé 

Definiamo le variabili Area 
Altezza di 


, Base ed 
tipo Doublé 



H Selezioniamo per tre volte un 
controllo Label dalla casella 
degli strumenti e disegniamo i tre 
controlli sulla form in corrispondenza 
dei tre TextBox disegnati in 
precedenza. 



Base = CDbl(TextBoxBase.Text) 
Altezza = CDbl(TextBoxAltezza.Text) 



Poiché i valori immessi in un 
TextBox sono di tipo String, 
dobbiamo utilizzare la funzione di 
conversione CDbl che converte una 
qualsiasi espressione in un valore di tipo 
Doublé. 




► 102 /Aprile 2005 



Visual Basic .NET 



T CORSI BASE 



PASSAGGIO 
DI ARGOMENTI 

Spesso quando una procedura viene chiamata 
all'interno di un'applicazione, non richiede ulte- 
riori informazioni per eseguire le proprie istruzio- 
ni, ma in generale, la procedura chiamata può 
richiedere dati all'applicazione. Per passare infor- 
mazioni ad una routine vengono usate delle varia- 
bili definite argomenti. Gli argomenti possono 
essere passati: 



• Ogni argomento facoltativo deve specificare un 
valore predefinito. 

• Ogni valore predefinito per un argomento facol- 
tativo deve essere un'espressione costante an- 
che se si tratta di zero o della stringa vuota. 

• Ogni argomento successivo ad un argomento fa- 
coltativo deve essere anch'esso facoltativo. 

La sintassi di una dichiarazione di procedura con un 
argomento facoltativo è la seguente: 




Per valore (di default) 
Per riferimento 



Sub NomeProcedura(ByVal argl As Tipol, Optional 

ByVal arg2 As tipo2 = default) 



Con il passaggio di argomenti per riferimento, la 
routine può modificare in maniera permanente il 
valore della variabile passata come argomento 
poiché ne viene passato l'indirizzo in memoria. 
Per passare un argomento per riferimento, è 
necessario utilizzare la parola chiave ByRef. Con il 
passaggio di un argomento per valore viene invece 
passata soltanto una copia della variabile, pertan- 
to se la routine ne modifica il valore, tale modifica 
viene applicata solo alla copia e non si propaga 
all'intera applicazione. Per passare un argomento 
per valore non è necessario scrivere la parola chia- 
ve ByVal, poiché VB.Net la scriverà in automatico. 



ARGOMENTI OPZIONALI 

Dalla versione 4 di VB è stata introdotta la possibi- 
lità di impostare gli argomenti di una routine 
come opzionali o facoltativi, utilizzando la parola 
chiave Optional nell'elenco degli argomenti. 
Gli argomenti opzionali devono essere sempre di- 
chiarati dopo gli argomenti obbligatori perciò, 
quando si specifica il primo argomento opzionale, 
anche gli argomenti successivi devono essere 
opzionali, e quindi dichiarati con la parola chiave 
Optional. Per utilizzare gli argomenti opzionali si 
devono osservare le seguenti regole: 



Quando si chiama una procedura con un argomen- 
to facoltativo, si può scegliere di non passare l'argo- 
mento. Se l'argomento opzionale non viene passato, 
la procedura utilizza al suo interno il valore predefi- 
nito. Se una procedura ammette più di un argomen- 
to facoltativo, è possibile scegliere di passare una 
qualsiasi serie di argomenti (anche vuota), l'unica 
regola da seguire è quella di utilizzare virgole in se- 
quenza per contrassegnarne la posizione. Se ad 
esempio si vuole chiamare una procedura che am- 
mette tre parametri opzionali passando soltanto il 
primo ed il terzo argomento, ma non il secondo, si 
deve scrivere: 

ProceduraEsempio(argl, , arg3) 'arg2 non viene passato 



CONCLUSIONI 

In questo articolo abbiamo accertato che è necessa- 
rio suddividere un programma VB.Net in program- 
mi più piccoli che siano più facili da scrivere, modi- 
ficare e comprendere mediante le procedure e le 
funzioni. 

Nel prossimo articolo inizieremo il viaggio nella pro- 
grammazione ad oggetti. 

Luigi Buono 



Un altro modo per 
definire una routine 
con argomenti 
facoltativi è quello di 
usare la tecnica 
dell'overload. Eseguire 
l'overload di una 
routine significa 
definire la stessa 
routine in più versioni, 
utilizzando lo stesso 
nome ma diversi 
elenchi di argomenti. 
Questo metodo 
diventa più oneroso 
con l'aumentare del 
numero degli 
argomenti facoltativi, 
ma ha il vantaggio di 
assicurare che la 
chiamata della 
procedura fornisca 
tutti gli argomenti 
facoltativi. La tecnica 
dell'overload sarà in 
ogni modo più chiara 
nei prossimi articoli. 



LA CHIAMATA ALLA FUNZIONE 



LA FUNZIONE AREATRIANGOLO 



Area = AreaTriangolo(Base, Altezza) 
TextBoxArea.Text = Area 



□ Poniamo la variabile Area, pari al 
valore restituito dalla funzione 
AreaTriangolo che si preoccupa di eseguire i 
calcoli. Infine visualizziamo nel TextBox 
corrispondente, il valore dell'area del 
triangolo. 



Public Function AreaTriangolo( ByVal Base As 

Doublé, ByVal Altezza As Doublé) As Doublé 

AreaTriangolo = (Base * Altezza) / 2 

End Function 



La funzione AreaTriangolo contiene il 
codice necessario per il calcolo dell'area 
del triangolo. Semplicemente, viene eseguito il 
prodotto del valore contenuto nella variabile 
Base per il valore contenuto nella variabile 
Altezza ed il risultato viene diviso per due. 



Aprile 2005/ 103 ► 





CORSI BASE T 



I 



Javascript 




Comprendere il Document Object Model 

Fondamenti 

di Javascript 

Le basi per usare il linguaggio principe per la programmazione web. 
Sia che stiate progettando una semplice pagina Html, sia che stiate 
creando un sito complesso, avrete a che fare con JavaScript 




Utilizza questo spazio per 
le tue annotazioni 



jn 




REQUISITI 



Conoscenze richieste 



Qj 



d J J 



Tempo di realizzazione 



Una pagina web è visualizzata in un browser, 
che a sua volta è un'applicazione installata 
su un PC locale. I browser interpretano le 
pagine HTML ricevute dal server e le mostrano a 
video. JavaScript é un linguaggio lato client che dia- 
loga con il Browser consentendo di modificare la 
visualizzazione di una pagina dopo che essa e stata 
ricevuta dal server, e senza dover dialogare con esso. 
Appare ovvio che JavaScript debba interagire con il 
browser accedendo a proprietà contenute nella 
pagina. Il DOM formalizza la struttura ad oggetti 
che un qualunque browser deve mettere a disposi- 
zione del programmatore e con la quale è possibile 
effettuare operazioni che modificano la pagina web, 
impostando e/o leggendo delle proprietà e richia- 
mando metodi appartenenti a questi oggetti (come 
caselle di testo, tabelle, liste valori,...). 
Nel corso del tempo sono stati erogati diversi stan- 
dard di DOM, e alcuni browser hanno introdotto dei 















H - 1 


H - 






H - 1 


— J Checkboi 


WilKlOW 


— J Applet 


J FileUpload 










H — h- 


J Base 


H - 








■A - 1 


— J Bfxly 


H — 








H » 


.1 r,„ 1 




J Option 


1 1 










-^ Frame8e , 


H - 1 


H - 








— J IFrame 


H Layer 


— J TextArea 








— J Histor, 


H - 1 


H » 


— J Location 


Orcler List 


H - 








J N«i(j.rtOI 


Unordered List 


L^ Rese, 






L^ 


— J Tables 







modelli proprietari, perciò nel programmare in 
JavaScript é importante affidarsi a standard ben 
riconosciuti e definiti. Non ci addentriamo per ora 
in ulteriori dettagli teorici, che analizzeremo meglio 
in articoli successivi. Per ora basti sapere che è stato 
definito un modello ad oggetti specifico per docu- 
menti HTML, sul quale il linguaggio Javascript è in 
grado di operare; la rappresentazione grafica del 
modello ad oggetti è riportata nella Figura 1. Il gra- 
fico mostra gli oggetti che più comunemente ven- 
gono utilizzati nella programmazione Javascript. I 
quadratini rappresentati in scuro sono gli oggetti 
non ufficialmente riconosciuti dal W3C ma comun- 
que supportati dai browser, con limitazioni che 
vedremo più avanti. Il primo esempio che ci accin- 
giamo a seguire riguarda il noto elemento TextArea 
di HTML, che disegna una finestra di testa pronta a 
essere riempita da un'input. 



HTML E GLI OGGETTI 

TextArea é rappresentata da un interfaccia HTML- 
TextAreaElement, o viceversa potremmo dire che è 
HTMLTextAreaElement implementata nel browser 
da un oggetto che possiamo chiamare textarea (il 
nome dipenderà dal browser, ma non è importante 
nel nostro ragionamento) una cui istanza viene rap- 
presentata con la seguente espressione all'interno 
di una pagina HTML: 



<textarea na me = "TextArea" rows="20" cols= 


"80"> 


Io sono una area di testo a linea multipla, 


con 20 righe e 80 colonne. 


</textarea> 



Fig. 1: La rappresentazione grafica del modello ad 
oggetti in Javascript 



Ad esempio, L'attributo cols dell'interfaccia HTML 
TextAreaElement farà riferimento all'attributo omo- 
logo del campo di textarea; quindi c'è da aspettarsi 




► 104 /Aprile 2005 



Javascript 



T CORSI BASE 



che si possa mediante Javascript leggere e/o modifi- 
care il valore del parametro cols della nostra texta- 
rea. In effetti e proprio così e più avanti vedremo 
come fare. In altri termini, la specifica del W3C rela- 
tive al DOM per i documenti HTML mette in rela- 
zione l'interfaccia dell'oggetto del DOM con il tag 
HTML corrispondente e di questo oggetto, e quindi 
del tag, definisce metodi e proprietà che sono (o 
dovrebbero) essere supportati dai browser. 
Tipicamente, una proprietà o un metodo che viene 
ufficialmente inserito sul DOM del W3C è imple- 
mentato dai browser principali, ma è sempre consi- 
gliabile verificarlo direttamente sul sito del produt- 
tore del browser; è sempre buona norma sia effet- 
tuare un test dei propri scripts su più browser al fine 
di verificarne le compatibilità sia non usare metodi e 
proprietà specifiche di un particolare browser che in 
genere non sono supportate da altri browser. 



INSERIMENTO 
DI JAVASCRIPT 
IN PAGINE HTML 

Per prima cosa occorre vedere come sia possibile 
inserire del codice Javascript all'interno di una pagi- 
na HTML, quale potrebbe essere la seguente: 



<html> 


<head> 


<title>II mio primo programmò 


javascript</title> 


</head> 


<body> 


<hl>Esempi di 


inclusione di 


codice Javascript</hl> 


</body> 


</html> 



Un'istruzione JS può essere inserita in una pagina 
HTML nei seguenti modi: 

• Primo Metodo: mediante l'uso del tag <script> 
direttamente nella pagina HTML 

<script type="text/javascript"> 

document.write("<b>"); 

document.write("Ciao mondo! "); 

document.write("Sono il mio primo programma 
Javascript!"); 

document.write("</b>"); 

</script> 

• Secondo Metodo: mediante l'uso del tag 
<script> che richiamo file JS esterni 

<script src="javascript/Routines.js" type="text/ 

javascript"x/script> 

Il file Routines.js è un semplice file di testo il cui 



contenuto è il seguente, ed al quale potranno 
essrere in seguito aggiunte altre funzioni: 

function TipoBrowser() 
{document.write(window.navigator.appCodeName);} 

• Terzo Metodo: All'interno di routine di eventi di 
oggetti HTML 

<input type="button" value="Metodo3" name="Metod3" 
id="ExlM3" onClick="javascript:alert('Hello world')"> 



s |p http://www.w3 riTML-20030109/html. 

gì) . t v C Cerca - 



( \] Opzioni ;, . Popup bloccate (69) - & Hotmail 



Interface HTMLTextAreaElement 

Multi-li ne text fi elei . See the '.; ■ in HTML 4.0 1 . 



: 



// Modified in DOH Level 2: 

attribute DOMStuing det t 

readonly atttribute ..■'■; 

attiribute DOHStiring 

atteibute boolean disat 

'. DOMString nane ; 



atteibute long 

■ . e ■ ; - .'...■,'. ' , : ' : '.:. i ■ 

.-.. . i xbutrs DOHScs ins 



Attributes 

accessKey Of type DOMString 

' ; ".: ><ì <>\ 

4.01. 

cols Of type long 



Fig. 2: Definizione dell'interfaccia 
HTMLTextAteaElement 

Il metodo migliore da utilizzare dipende dal conte- 
sto. Nel caso di brevi istruzioni può essere utilizzato 
il terzo metodo. In genere il secondo metodo è pre- 
feribile in quanto il codice rimane più strutturato e 
separato dalla parte HTML. Inoltre può essere riuti- 
lizzato su più pagine HTML, cosa che risulta molto 
utile nel caso di funzioni generalizzate. Il primo 
metodo è consigliabile nel caso in cui il codice java- 
script sia utilizzato solo per la pagina nella quale 
viene inserito. Un esempio di pagina HTML mista 
con funzioni JavaScript é il seguente: 

<html> 

<head> 

<title>II mio primo programma javascript</title> 

<!-- Secondo Metodo — > 

<script src="javascript/Routines.js" 

type="text/javascript" > 

</script> 



</head> 



<body> 



<hl>Esempi di inclusione di codice Javascript</hl> 



<P> 



Il primo metodo restituisce il classico 'Hello 
World' in grassetto. . 



</p> 



<!-- Primo Metodo --> 



<script type="text/javascript"> 




document.write("<b>"); 



Aprile 2005/ 105 ► 





CORSI BASE T 



I 



Javascript 





Nella progettazione di 

applicazioni web, i 

linguaggi che vengono 

utilizzati per lo sviluppo 

di tali applicazioni sono 

sostanzialmente di due 

tipi: 



E Linguaggi lato Client: 

tali linguaggi, tra i quali 

possiamo annoverare 

VisualBasic Script e 

Javascript, permettono 

di interagire 

principalmente con gli 

elementi HTML 

componenti la pagina 

senza dover scambiare i 

dati con il server. 

Questo permette di 

ridurre drasticamente i 

tempi di esecuzione 

delle istruzioni, ma 

rende necessario il 

dover conoscere il tipo 

di browser sul quale 

questi script verranno 

eseguiti. 

E Linguaggi lato Server: 

tali linguaggi, tra i quali 

possiamo annoverare 

PHP, ASP, Coldf usion, 

JSP, Perl, C CGI, etc 

vengono interpretati 

dal server, che esegue le 

istruzioni e presenta i 

dati. E 1 compito 

dell'utente manipolare i 

dati dinamici e 

presentarli sotto forma 

di codice HTML. 

Alcune operazioni, quali 

ad esempio l'accesso a 

database o scrittura di 

file, è possibile 

effettuarle solo 

avvalendosi di linguaggi 

di scripting lato server, 

mentre per le 

interazioni con gli 

elementi della pagina è 

sicuramente più 

conveniente utilizzare 

linguaggi lato client. 



document.write("Ciao mondo! 


! "); 


document.write("Sono il mio 


primo programma 
Javascript!"); 


document.write("</b>"); 


</script> 


<P> 



Il secondo metodo richiama la funzione TipoBrow- 
serO definita nel file Routines.js della cartella 'java- 
script'. Cliccando sul pulsante visualizzato viene 
richiamata la funzione in questione. 



</p> 


<!— Secondo metodo — > 


<form name=" 


frmTerzoMetodo" id= 


= "frmTerzoMetodo" > 


<input type 
"Metodo2" id= 


="button" 
= "ExlM2" 


' value=' 
onClick= 


'Metodo2" name= 
= "TipoBrowser()"> 


</form> 


<P> 



Il terzo metodo visualizza un messaggio di popup. 
Allo stesso modo dell'esempio precedente sarà ne- 
cessario cliccare sul pulsante per richiamare la fun- 
zione corretta 



</P> 



<!— Terzo metodo --> 



<form name= "frmTerzoMetodo" id= "frmTerzoMetodo" > 
<input type="button" value="Metodo3" name= 

"Metod3" id = "ExlM3" onClick="javascript:alert 

('Hello world')"> 



</form> 



</body> 



</html> 

Nell'intestazione, all'interno del tag <head> viene 
inserito il tag script nel quale sono impostati gli attri- 
buti: 

• src che punta al file Javascript (con estensione js) 
posizionato nella cartella denominata "java- 
script" relativamente alla posizione del file 
HTML 

• type che indica il tipo di file puntato da src il cui 
valore "text/javascript" sta ad indicare che il file 
è di testo e che contiene istruzioni Javascript. 

In questo modo viene applicato il secondo metodo 
di inclusione. Scendendo verso il basso all'interno di 
un altro tag <script> troviamo del codice Javascript 
composto da una serie di istruzioni: document.write 
("Una stringa di testo... "). Si noti innanzi tutto che le 
stringhe in parentesi possono essere sia stringhe di 
testo che tag HTML (nel nostro esempio il tag per 
rendere il grassetto <b> ). Questo è un primo esem- 
pio di applicazione del modello del DOM. La classe 
document che implementa l'interfaccia HTMLDo- 
cument, che deriva dalla classe padre window, se- 



condo le specifiche del W3C ha un metodo denomi- 
nato write(in DOMString text), il cui scopo è quello 
di scrivere sul documento (ossia la pagina HTML) la 
stringa text che gli viene passata come parametro. In 
definitiva, con questa istruzione si può scrivere 
HTML all'interno della pagina del documento. 
Questo rappresenta un esempio di inclusione di 
codice Javascript all'interno della pagina HTML. 
Proseguendo ancora con il codice abbiamo un 
esempio di funzione Javascript richiamato dall'in- 
terno di un tag HTML. In particolare, la funzione 
TipoBrowserO definita nel file esterno Routines.js 
viene richiamata in seguito alla pressione del pul- 
sante etichettato con 'Metodo2', che scatena l'even- 
to onClick del pulsante stesso. L'ultimo esempio è 
simile al primo, con la differenza che invece di 
richiamare una funzione codificata in un file ester- 
no, la funzione è scritta direttamente all'interno del 
tag. Il codice onClick="javascript:alert('Hello world') 
significa "sul click del pulsante esegui il codice alert( 
'Hello world') che è scritto in linguaggio Javascript". 
Attenzione che scrivendo semplicemente onClick- 
"alert('Hello world') la cosa non funzionerebbe. 
Occorre sempre dire il tipo di linguaggio di scripting 
che si utilizza. La funzione Javascript alert("Messag- 
gio") invia una messaggio di popup con la stringa 
che gli si passa in input (l'equivalente della funzione 
MsgBox di Visual Basic 6). Si noti inoltre come il flus- 
so del linguaggio sia sequenziale e segua esattamen- 
te quello della creazione della pagina HTML, par- 
tendo dall'inizio della pagina e proseguendo sino al- 
la fine. Per finire non bisogna dimenticare che le no- 
stre pagine web possono essere visualizzate su 
browser che non hanno supporto di scripting o per i 
quali tale supporto è stato disabilitato. In tal caso 
viene in supporto il tag <noscript>. L'utilizzo del tag 
è il seguente: 

<script type= "text/javascript" > 

document. write("<b>Questa frase viene scritta solo 

se il browser supporta javascript</b>"); 

</scriptxnoscript> 

<b>Questa frase viene scritta solo se il browser non 

supporta gli script</b> 

</noscript> 

Per browser un po' datati, si rende necessario inseri- 
re il codice Javascript tra commenti di tipo HTML 
posti all'interno del tag <script>, in modo tale che il 
browser li salti e non li mostri sulla pagina. Un esem- 
pio potrebbe essere il seguente: 

<script type= "text/javascript" > 

<!-- 

document. write("<b>Istruzione commentata per 

compatibilità con browser datati</b>"); 

--> 

</script> 




► 106 /Aprile 2005 




Javascript 



i 



T CORSI BASE 




Sempre per browser datati è consigliabile specifica- 
re la versione del linguaggio Javascript che si sta uti- 
lizzando, ad esempio: 

<script type="text/javascript" language="javascriptl.2"> 

<!-- 

document.write("<b>Viene specificata la versione 

di Javascript per browser datati</b>"); 

— > 

</script> 

utilizzando l'opzione language del tag <script>. Così 
facendo, ci si garantisce che il vostro codice venga 
interpretato correttamente da browser "vecchio sti- 
le", senza per altro creare problemi ai browser più 
modermi. Se la versione non viene specificata, il 
browsere usa l'ultima versione di Javascript che ha 
disponibile. L'ultima versione disponibile di java- 
script è la 1.6, supportata solo da alcuni browser. 
Leggete il box relativo alla versione di Javascript per 
ulteriori simpatici approfondimenti sulla questione. 
Personalmente consiglio comunque sempre di 
testare il software su differenti browser che pensiate 
possano essere utilizzati dalla utenza della vostra 
applicazione web. 



EDORA 

UN PO' DI CODICE... 

...che non fa mai male. Prendete il vostro editor di 
testo preferito e copiate il codice che segue (che 
potete trovare anche nel software messo a disposi- 
zione con l'articolo): 

<html> 

<head> 

<title>Javascript - Articolo 1 - parametri del 

browser</title> 

</head> 

<body> 

<hl>Quello che avreste sempre voluto sapere del 

vostro browser... </hl> 

<script type="text/javascript"> 

function TipoBrowserQ 

{ document.write("<i>Nome del browser: </i>"); 
document.write(window.navigator.appName); 



document.write("<br>"); 



document.write("<i>Versione del browser: </i>"); 

document.write(window.navigator.appVersion); 

document.write("<br>"); 



document.write("<i>Sotto-versione del browser: </i>"); 
document.write(window.navigator.appMinorVersion); 
document.write("<br>"); 



document.write("<i>Code name del browser: </i>"); 

document.write(window.navigator.appCodeName); 

document.write("<br>"); 



document.write(window.navigator.browserLanguage); 

document.write("<br>"); 

document.write("<i>l cookie sono abilitati o no ?: </i> M ); 

document.write(window.navigator.cookieEnabled); 

document.write("<br>"); 

document.write("<i>Stai lavorando in modalità 

on-line oppure no?: </i>"); 

document.write(window.navigator.onLine); 

document.write("<br>"); 

document.write("<i>II vostro sistema operativo: </i>"); 

document.write(window.navigator.platform); 



document.write("<br>"); 



document.write("<i>l_a lingua del vostro sistema 

operativo: </i>"); 

document.write(window.navigator.systemLanguage); 
document.write("<br>"); 



document.write("<i>l_a classe della CPU ?: </i>"); 
document.write(window.navigator.cpuClass); 



document.write("<br>"); 



document.write("<i>Intestazione dello user-agent 

inviato dal vostro browser: </i>"); 
document.write(window.navigator.userAgent); 
document.write("<br>"); 



document.write("<i>Intestazione della lingua dello 
user-agent inviato dal vostro browser: </i>"); 

document.write(window.navigator.userLanguage); } 
TipoBrowserQ; 



</script> 



</body> 



document.write("<i>Linguaggio del browser: </i>"); 



</html> 

Salvate il file come Browser.html ed aprite il file nel 
vostro browser web; potrete visualizzare un po' di 
informazioni sul vostro browser. Nel codice ci sono 
molti degli elementi di Javascript che utilizzeremo 
nel seguito. Ovviamente, l'inserimento di codice 
Javascript in una pagina HTML (si è scelto per sem- 
plicità il primo metodo). Viene poi definita una 
funzione Javascript denominata TipoBrowser() che 
viene richiamata subito dopo, all'interno dello 
stesso tag script. Non ci soffermeremo oltre sul 
significato delle proprietà del browser richiamate 
nello script, del resto immediatamente comprensi- 
bili e sulle quale discuteremo in dettaglio nel pro- 
seguo degli articoli. 



CONCLUSIONI 

In questa puntata avete imparato le basi del lin- 
guaggio Javascript ed avete potuto creare un esem- 
pio di programma (che non è il solito 'Hello 
World') che vuole evidenziare anche un po' le po- 
tenzialità del linguaggio. 

Nelle prossime puntate ci addentreremo nella sin- 
tassi del linguaggio. 
L'avventura è appena iniziata... 

Danilo Fadda 




All'interno del tag 
<script> viene utilizza- 
to sovente l'attributo 
language, che viene 
utilizzato dai vecchi 
browser sia per capire 
quale versione di java- 
script viene utilizzata 
nel codice contenuto 
all'interno del tag, sia 
per capire se tale ver- 
sione viene supportata 
dal browser stesso. Ad 
esempio: 



<script language= 

"Javascript! .2"> 

....codice Javascript... 
</script> 

Tale attributo non 
viene utilizzato all'in- 
terno degli script del- 
l'articolo, in quanto 
deprecato da W3C a 
favore dell'attributo 
type del tag <script>. 
In articoli successivi 
approfondiremo l'ar- 
gomento, non banale, 
relativo alla versione 
di Javascript. 



Aprile 2005/ 107 ► 





CORSI BASE T 



I 



Mobile 




Programmazione dei cellulari in C++ 



Symbian 
primi passi 

In questo articolo e nei successivi impareremo come programmare 
applicazioni per il sistema operativo Symbian usando C++ 
Utilizzare C++ ci garantisce massima flessibilità e portabilità 




L| elevato uso dei dispositivi mobili ha porta- 
to negli ultimi anni ad un'evoluzione delle 
piattaforme hardware e software per stru- 
menti come cellulari, notebook e palmari. Il telefo- 
nino in particolare è diventato uno strumento di pri- 
maria importanza nella vita di tutti i giorni e l'uten- 
te vuole avere a portata di mano tutto ciò che offre 
un PC tradizionale. Symbian OS è una tra le princi- 
pali tecnologie moderne che rendono il cellulare 
uno strumento completo. Durante il corso conosce- 
remo meglio la piattaforma e impareremo a sfruttar- 
ne le funzionalità. 



Setup Environment Variables 



m 



T i H i i ri n r ti"- r i > ~\ ir 1 1 u 

build tools frorn a comrmand prompt are saved in the VCVARS32.BAT 
inyour BIN directory. 



\7 Fiegister Environment Variables 

Turn on this option to regi: nent variables for running Visual C+- 

tools from the command line. 



Fig. 1: È importante settare variabili d'ambiente 



jn 




REQUISITI 



3al Basi di C++ 



Visual C++ 



^^^_J _J 



Tempo di realizzazione 




INSTALLIAMO 
GLI STRUMENTI 

Lo strumento principale per un programmatore è 
l'SDK {Software Development Kit). È necessario 
quindi procurarsi l'SDK relativo al cellulare su cui si 
vuole scrivere l'applicazione. Ogni azienda che pro- 
duce cellulari Symbian OS mette a disposizione il 
proprio SDK, che può anche riferirsi a più modelli. 
All'indirizzo http://www.forum. nokia. com/main/0, 
6566,034-4,00.html si possono trovare i kit per i cel- 
lulari Nokia. Scriveremo software per il Nokia 7650, 
usando l'SDK 1.2, ma con qualche piccola modifica 
è possibile sfruttare lo stesso codice per il Nokia 
6600 usando l'SDK 2.0. 

Un elenco completo dei cellulari Symbian è reperi- 
bile all'uri 
h ttpj/www. symbian. com/phones/index. h tml. Nella 
fase di build dell'applicazione è indispensabile un 
interprete Perl. ActivePerl fa al caso nostro {http:// 
www.activeperl xom/Products/ ActivePerl/), ricordan- 
doci di settare opportunamente le variabili d'am- 
biente (Figurai). 

Abbiamo inoltre bisogno di Microsoft Visual C++ 
{http://msdn. microsoft, com/visualcf) . 



► 108 /Aprile 2005 



CREAZIONE 
DEL PROGETTO 

Una semplice applicazione in Symbian richiede la 
creazione di diversi file, siano essi sorgenti o risorse. 
Il software ApplicationWizard di casa Nokia ci viene 
in aiuto. Con l'SDK 1.2 è necessario aggiungere il 
template di creazione direttamente in Visual C++. 
Copiamo quindi i file presenti nella cartella \Sym- 
bian\6. 1 \Series60\Series60Tools\applicationwizard\ 



Series 60 AppWizaid v 1 .9 - Step 1 of 4 




Co :■ i gì- . [e] Noi al orpora n n 



What type of . i| li i > I il e to create? 

<? EIK0N Control 
C Dialogbased 

Suppo : view archsiecfu : 



Application Title: JHelloWorld 



Unicode UID: 0x0C3C6DB2 

REMEMBER to use DIFFERENT UID for everv new 
application. 



ipport for: 
r INI file 
\~ docurr 



Back Ne>:t> li Finish il Cancel Help 



Fig. 2: Setti amo il nome dell'applicazione nel wizard 
lasciando inalterato il resto 



Mobile 



T CORSI BASE 



nel path dei template \Microsoft Visual Studio\Com- 
mon\MsDev98\Template. Avviamo Visual C++ e dal 
menu "File" selezioniamo "New". Nella tab dei pro- 
getti troviamo adesso "Series 60 AppWizard". Selezio- 
niamolo e settiamo nome e path del progetto, nel 
nostro esempio c:\HelloWorld. Per la creazione di un 
nuovo progetto è necessario specificare solo il titolo 
dell'applicazione, lasciando invariato tutto il resto 
(Figura 2). Nella directory c:\HelloWorld\src sono 
stati creati i sorgenti di un programma base. Per la 
comprensione del codice diamo uno sguardo al lin- 
guaggio utilizzato. 



C++ PER SYMBIAN OS 

Sebbene C++ sia il linguaggio utilizzato per Sym- 
bian OS, esistono alcune differenze e convenzioni 
particolari sui nomi. I nomi delle classi cominciano 
con una delle lettere C, T, R o M, con i seguenti si- 
gnificati. 

• C: Classe allocata in memoria derivata da CBase 

• T: Classi che non contengono nessun oggetto 
esterno 

• R: Classi che contengono collegamenti a risorse 
reali 

• M: Classi di interfaccia 

In Java ogni classe discende indirettamente da 
Object, in C++ per Symbian ogni classe discende da 
CBase. La creazione di un nuovo oggetto si effettua 
con il seguente costrutto: 

ICMiaClasse mioOggetto = new (ELeave) CMiaClasseQ; 



introduce il discorso delle eccezioni. In 
C++ e in Java è previsto un costrutto try-catch per la 
cattura delle eccezioni, facendo scorrere l'errore tra- 
mite un oggetto. In C++ per Symbian si parla più 
propriamente di "leave". Non viene più gettata 
un'eccezione ma effettuato un leave. La funzione 
User::Leave() è l'analogo del throw. Il leave produce 
un codice d'errore di 32 bit anziché un oggetto, ren- 
dendo meno pesante la gestione. Un "panie" è un 
errore non catturabile e causa la terminazione del 
processo. La funzione relativa è User::Panic(). I leave 
possono causare spreco di memoria e di risorse. 
Vediamo il seguente codice: 

i void mioMetodoQ { 



miaClasse non viene effettuato. Perdendo il riferi- 
mento all'oggetto non vi è alcuna possibilità di libe- 
rare memoria. In un dispositivo portatile, dove le ri- 
sorse sono scarse, ciò è importante! 

3 è la soluzione al problema. 



Cleanup Support 



CLEANUP SUPPORT 

Al verificarsi di un errore il framework Symbian libe- 
ra la memoria occupata da tutti gli oggetti contenu- 
ti nello stack "Cleanup". La seguente gestione: 



void mioMetodoQ { 

CMiaClasse * mioOggetto = new (ELeave) CMiaClasseQ; 

CleanupStack: :PushL(miaClasse); 

miaClasse -> metodoConLeaveLQ; 



CleanupStack: :Pop(); •- 



delete miaClasse; 




Fig. 3: Un'immagine evocativa dei telefoni Symbian 
OS in commeteio 

permette di tenere traccia del riferimento all'ogget- 
to. Se metodoConLeaveLO esce a causa di un errore, 
la memoria di mioOggetto viene comunque liberata. 
Un'ultima importante considerazione riguarda il 
leave all'interno di un costruttore. Il costruttore di 
una classe viene richiamato solo dopo che è stata as- 
segnata la memoria per il nuovo oggetto. Un "leave" 
in fase di costruzione porterebbe ad uno spreco. In 
questo caso viene utilizzata una tecnica chiamata 
"Costruzione in 2 fasi". Ecco un esempio: 

class CMiaClasse { 

CAItraClasse * nuovoOggetto; 

CMiaClasseQ {} 

ConstructLQ { 

// L'oggetto viene istanziato qui anziché nel 

// costruttore 



nuovoOggetto = new (ELeave) CAItraClasseQ; } 



} 



CMiaClasse * mioOggetto = new (ELeave) CMiaClasseQ; CMiaClasse* oggetto = new (ELeave) CMiaClasseQ; 



miaClasse -> metodoConLeaveLQ; #- 
delete miaClasse; 



Se 



metodoConLeaveLQ 



si interrompe per un errore, 
non termina la sua esecuzione e delete 



CleanupStack: :PushL(oggetto); 



oggetto -> ConstructLQ; 



CleanupStack: :Pop(); 

Il costruttore non si preoccupa di gestire situazioni 
potenzialmente rischiose, lasciando il compito ad 





I TUOI APPUNTI 



Utilizza questo spazio per 
le tue annotazioni 



Aprile 2005/ 109 ► 





CORSI BASE T 



I 



Mobile 





una funzione secondaria che per convenzione è 
chiamata ConstructLO, sulla quale è possibile ricor- 
rere al Cleanup Support. Un utile approccio consiste 
nell'utilizzare due metodi statici per effettuare la 
costruzione in 2 fasi: 

static CMiaClasse * CMiaClasse: :NewLC() { 

CMiaClasse * questo = new (ELeave) CMiaClasseQ; 

CleanupStack: :PushL(questo); 

questo->ConstructL(); 



return questo; } 



static CMiaClasse * CMiaClasse: :NewL() { 



j CMiaClasse * oggetto = NewLCQ; 



CleanupStack: :Pop(); 



return oggetto; 



La funzione E permette di ottenere un'istanza 
della classe. La lettera "L" finale rappresenta per con- 
venzione la possibilità che essa effettui un leave, e la 
lettera "C" implica che l'espulsione dallo stack è a 
carico del metodo chiamante. 



HELLOWORLD 

Per la stesura di HelloWorld utilizziamo lo scheletro 
dei sorgenti creati precedentemente con Visual C++. 
Apriamo il file c:\HelloWorld\src\HelloWorldAppUi.cpp 
e, nella funzione HandleCommandLO, assicuriamo- 
ci che il blocco "case EhelloworldCmdAppTest:" con- 
tenga le seguenti righe: 

_LIT(message,"Hello World!"); 

CAknConfirmationNote* note = new (Eleave) 

CAknConfirmationNote(); 
note->Executel_D(message); 

Inoltre aggiungiamo: 

#include <aknnotewrappers.h> 

La descrizione dettagliata del framework grafico ver- 
rà trattata nel successivo articolo. È importante 
adesso concentrarsi sulla procedura di build, che 
permette l'esecuzione del software sul nostro cellu- 
lare. 



EREDITARIETÀ MULTIPLA 



In C++ per Symbian l'ereditarietà 
multipla è stata sostituita da sem- 
plici regole. Tali regole riprendono 
la comoda sintassi Java. 

Classe C: Classe (concetto classico) 
Classe M: Interfaccia 

• Possiamo derivare una classe C 
da una sola classe C e zero o 
più classi M. 

• La derivazione dalla classe C 
deve essere dichiarata per 



prima. 

Non possiamo derivare una 
classe C da due classi M con- 
temporaneamente se la prima 
è derivata dalla seconda. 



MRepe ribile 



CHome ' 



i 



V 



A MCredibile ' 



A MAscoltatorel • 



151 



CGabriele 



|MAscoltatore2 

-V— ' 



L'ULTIMA FASE: 
IL BUILD 

Prima di installare il software sul telefonino è neces- 
sario ovviamente compilarlo. Il file c:\HelloWorld\ 
group\helloworld.mmp contiene le specifiche di 
progetto. All'interno troviamo una riga SOURCEper 
ogni file sorgente: 

SOURCE SourceFile.cpp 

Apriamo una console testuale e portiamoci nella 
directory c:\HelloWorld\group\. 
Lanciamo i due comandi: 



CREIAMO LA PRIMA APPLICAZIONE 




Fui youf conveniente, the envkmrnert vanables required lo run 
build tools fronn a command prompt art in th CVARS32.BAT 

inyour E! IN directory. 



• Register Environrment Variables 



T i ii 1 1 « i li i inm 1 1 h • register environnient variables Sor running Visual C++ 
tools ffom the command line- 



: 



O Installiamo gli strumenti che ci 
servono: Nokia SDK 1.2, Microsoft 
Visual C++ 6.0 e ActivePerl. Durante 
l'installazione di Visual C++ ricordiamoci 
di settare le variabili d'ambiente come 
mostrato in figura. È possibile farlo 
anche tramite VCVars32.BAT. 




El Aggiungiamo a Visual C++ il tem- 
Efl piate Nokia per la creazione assi- 
stita di un'applicazione base. Copiamo 
avkonappwiz.awx e avkonappwiz.hlp da 
Symbian\6.1\Series60\Series60Tools\appli 
cationwizard a Microsoft Visual 
Studio\Common\MSDev98\Template\ 



Series 60 AppWizard v 1 .9 - Step 1 of 4 



"^ 




v'hai type al application wouldyou h(.g to create? 
C EIKON Control 
C Dialog based 

Si pipasi ,.,-,-,.., ;. chilecture 



■ii 'n- 



Unicode UID: |0x0CA363FE 

REMEMBER to use DIFFERENT UID for every new 



. ' !■■■ li 'in i ; ■' • . ',,.!'. 



<Beck | Ne«t> | 



J 



J 



Apriamo Visual C++ e clicchiamo 
su File, poi su New. Dalla tab pro- 
jects selezioniamo Series 60 AppWizard, 
digitiamo il nome del progetto, 
settiamo la directory e premiamo OK. 
Nel nuovo dialog inseriamo il nome 
dell'applicazione e clicchiamo su Finish. 




► 110 /Aprile 2005 




Mobile 



i 



T CORSI BASE 




bldmake bldfiles (crea il file abld.bat) 

abld build thumb urei (compilazione e link) 

Abbiamo così creato il programma HelloWorld.app e 
alcuni file necessari alla sua esecuzione. Tali file ri- 
siedono in \Symbian\6.1\Series60\Epoc32\release\ 
thumb\urel\. 

Per l'installazione sul cellulare abbiamo due possibi- 
lità. È abbastanza scomodo copiare tutti i file nella 
directory c:\system\apps\helloworld del dispositivo 
mobile, perciò decidiamo di creare un file installati- 
vo helloworld.sis che farà il lavoro per noi. I file .sis 
sono riconosciuti dai cellulari Symbian come soft- 
ware autoinstallanti. Per creare un file .sis è necessa- 
rio creare un file di testo .pkg che contiene: nome 
dell'applicazione, numeri di versione, parametri di 
compatibilità e file da installare. Nel nostro esempio 
Visual C++ l'ha già creato per noi. In console, posi- 
zioniamoci nella directory c:\HelloWorld\install e 
digitiamo: 

makesis helloworld.pkg 

Se tutto va a buon fine nella stessa directory trovia- 
mo helloworld.sis. Installandolo sul cellulare ed ese- 
guendolo otteniamo le schermate in Figura 4. 





r p-^HelloHorld 

Exomple Uiew 


Example Uiew 




Hello World! -/ 




Exit [ 




Seleziona Rnnulla 





L'aggiunta di ulteriori file al pacchetto comporta la 
modifica di helloworld.pkg, che presenta una sin- 
tassi banale. Un ottimo strumento per la creazione 
dei file .sis è Sisar, distribuito insieme a qualunque 
SDK e richiamabile dal menu START. 



CONCLUSIONI 

Abbiamo visto come creare una semplice applica- 
zione per il Nokia 7650 sfruttando l'SDK 1.2 forni- 
to dalla Nokia. Più in particolare è stato necessario 
aggiungere alcune istruzioni in punti ben definiti 
di un progetto base creato con appositi strumenti. 
Sebbene sia necessario puntare ad una specifica 
piattaforma di sviluppo, le conoscenze acquisite 
nell'articolo ci permettono anche una migrazione 
a diversi o a nuovi dispositivi portatili basati su 
Symbian OS, il tutto con "poco" sforzo. 
Non è tuttavia da escludere la possibilità che il co- 
dice da noi scritto diventi "inutile", se pensiamo al- 
la facilità con cui al giorno d'oggi sostituiamo il 
cellulare con uno nuovo. La chiave di tutto rimane 
comunque il continuo aggiornamento. 

Antonio Trapani 



Fig. 4: Un altro esempio dell'applicazione in esecuzione 



C++ VS JAVA 



Sebbene Java sia un linguaggio a 
oggetti flessibile e affidabile, 
esonerando il programmatore dal 
gestire la memoria, esso presenta 
delle debolezze. A differenza dei 
PC, dove la potenza di calcolo 
riduce la differenza di prestazione 
di un programma scritto in C++ e di 
uno scritto in Java, i dispositivi 
portatili hanno risorse limitate. Su 




un cellulare, Java è più "pesante". 
Al giorno d'oggi inoltre le JVM non 
offrono il pieno controllo dei 
dispositivi, mancando ad esempio 
di funzionalità importanti come 
l'accesso al filesystem o 
l'esecuzione di metodi nativi. L'uso 
del C++, grazie alla piattaforma 
Symbian, permette un controllo 
diretto su tutto il sistema. 



} i _ 1 i i i U f _ "_ I ,i -li 

sraitch ( ad: 



te ? he ì otto] LdCriidii pp lesi : 
{ 
_LIT(message, "Hello World!"); 

CilknConf irrnst ioiìNot-e * informar, lordiots = 

new (ELeave) CAknConf iirmationNote ( ) ; 

Liif oirroat ionMoce -xExei ufceLD (message) - 



:>i-k; 



; bere 



□ E il momento di aggiungere il 
nostro codice. 
Apriamo c:\HelloWorld\src 
\HelloWorldAppUi.cpp e all'interno 
della funzione HandleCommandLQ 
inseriamo le istruzioni riportate 
nell'articolo. 




H Apriamo una console dei 
comandi e posizionamoci nella 
directory group appartenente al 
nostro progetto. Digitiamo bldmake 
bldfiles e subito dopo abld build 
thumb urei. Il programma è compilato 
e pronto per essere trasferito. 



HPer creare il file d'installazione 
portiamoci invece nella directory 
instali e digitiamo makesis Hello- 
world.pkg. Trasferiamo Helloworld.sis 
sul telefonino, installiamolo e 
lanciamolo. Se tutto è andato a buon 
fine vedremo la finestra di HelloWorld. 



Aprile 2005/ 111 * 




TIPS & TRICKS T I Una raccolta di trucchi da tenere a portata di... mouse 



I trucchi del mestiere 

Hps & TVicks 

Questa rubrica raccoglie trucchi e piccoli pezzi di codice, frutto dell'esperienza di chi programma, che solitamente non 
trovano posto nei manuali. Alcuni di essi sono proposti dalla redazione, altri provengono da una ricerca su Internet, altri 
ancora ci giungono dai lettori. Chi volesse contribuire, potrà inviare i suoi Tips&Tricks preferiti. Una volta selezionati, 
saranno pubblicati nella rubrica. Il codice completo dei tips è presente nel CD allegato nella directory \tips\ o sul Web 
all'indirizzo: cdrom.ioprogrammo.it. 




JAVA 



INTERROGARE LO STATO 
DELLE PORTE 

Ecco un semplice tip per interrogare lo stato delle nostre 
porte(seriali e parallele). Il tip fa uso del package commapi scari- 
cabile dal sito della sun. Il programma innanzitutto crea la lista 
delle porte installate sulla nostra macchina e tramite 1' enumera- 
re invocando su ogni porta il metodo open per testarne la dispo- 
nibilità,se tale metodo solleva l'eccezione "javax.comm.Portln- 
UseException " allora significa che la porta in esame è occupata da 
qualche altra applicazione. 

Tip fornito dal sig. Avolio Antonio 

package comunicazioneporte; 

import java.util.*; 

import javax.comm.*; //package contenente le commapi 

public class scansionePorte { 



public static void main(String[] args) { 



//Creazione della lista delle porte installate sulla macchina 

Enumeration portelnstallate = 

CommPortIdentifier.getPortIdentifiers(); 



//Oggetto che interaggisce con i driver 



CommPortldentifier portaID=null 



//Enumerazione delle singole porte 



while (portelnstallate.hasMoreElementsQ) { 



try { 



portalD = (CommPortldentifier) portelnstallate.nextElementQ; 
System.out.print(portaID.getName()); 



//verifica se si tratta della porta seriale 



if (portalD.getPortTypeQ == 1) { 



System.out.print(" SERIALE"); 



portaID.open("prova", 100); 



Jl 



//verifica se si tratta della porta parallela 



if (portalD.getPortTypeQ == 2) { 



System.out.print(" PARALLELA"); 



portaID.open("prova", 100); 



System.out.print(" Porta libera"); 



Jl 



catch (javax.comm.PortlnUseException e) { 



if((e.currentOwner).equals("Unknown Windows Application")) 
System. out.print(" La porta "+portaID.getl\lame()+" e' 
occupata da un'applicazione di Windows"); 



else 



System. out.print(" La porta "+portaID.getName() + 

" "+e.currentOwner); } 



System.out.printlnQ; 



} //while 



Jl 




SESSI VB.IMET 



INVIARE E-MAIL CON .NET 

La soluzione che vi propongo permette di inviare mail grazie alle 
utilissime classi del framework .NET. Ma la novità sta nel fatto che 
ho aggiunto le istruzioni utili all'autenticazione verso il server 
SMTP che solitamente non sono documentate negli esempi che 
si trovano in rete. Utile per chi ha un sito in hosting ma non un 
server SMTP disponibile presso il proprio provider. Nell'esempio 
ho utilizzato il server di Spymac 

Tip fornito dal sig. Gianluca Negrelli 

Il classe per l'invio di mail attraverso un server SMTP 

// con autenticazione di user name e password 

// linguaggio c# 

// framework .NET 1.1 



// 26/01/05 



// autore Gianluca Negrelli 



using System. Web. Mail; 



namespace gn.utility 



{ 



public class classMail 



i_ 



public static bool InviaMail(string sBody, string sFrom, string 

sTo, string sSubject) 



V 112 /Aprile 2005 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse ■ T TIPS & TRICKS 



try 



// tentativo di invio mail con autenticazione 



// il server è spymac 



MailMessage MyMsg = new MailMessageQ; 



MyMsg.Body=sBody; 



MyMsg.From=sFrom; 



MyMsg.To=sTo; 



MyMsg.Subject=sSubject; 



// tentativo di autenticazione verso il server spymac 

MyMsg.Fields.Add("http://schemas. microsoft.com/cdo/ 
configuration/smtpauthenticate","!"); //basic authentication 
MyMsg.Fields.Add("http://schemas. microsoft.com/cdo/ 

configuration/sendusername", "xxxxxx@spymac.com"); 

//username 



MyMsg.Fields.Add("http://schemas. microsoft.com/cdo/ 

configuration/sendpassword", "xyz"); //password 

// tentativo di autenticazione verso il server spymac 

SmtpMail.SmtpServer="mail. spymac.com"; 
SmtpMail.Send(MyMsg); 



// comunica il buon fine 



return true; 



Jl 



catch 



_±_ 



Il comunica l'errore 



return false; 






IL TIP DEL MESE 

FATE VIBRARE LA VOSTRA JFRAME 



Il codice completo per far vibrare una 
JFrame (o qualsiasi altro JComponent). 
Per velocizzare il tremolio basta cambia- 
re il 50 della funzione trema() [che sareb- 
bero i millisecondi di occorrenza del ti- 
mer] : cambiandolo in 100 andrà più len- 
to; in 25 andrà più veloce. Per far durare 
il tremolio più tempo basta aggiungere 
istruzioni case alla funzione spostaFine- 
straQ e cambiare il 20 nell'istruzione if 
(numTremate == 20) con il numero di 
istruzioni case inserite. 

Tip fornito dal sig. Rosario Capparelli 

package trema; 

import java.awt.Point; 



import java.awt.event.ActionEvent; 



import java.awt.event.ActionListener; 



import javax. swing. JButton; 



import javax. swing. JFrame; 



import javax. swing. Timer; 



public class Trema extends JFrame{ 



Timer t; 



private int numTremate; 



private Point p; 



public Trema(){ 



this.setDefaultCloseOperation( 
EXIT_ON_CLOSE); 

JButton bottone = new JButton("trema"); 

bottone. addActionl_istener(new 
ActionListener(){ 



public void actionPerformed( 
ActionEvent argO) { 



tremaQ; 



»); 



this.getContentPane().add(bottone); 



this.packQ; 



this.setLocationRelativeTo(null); 



this.setVisible(true); 



} 



void trema(){ 



= new Timer(50,new Actionl_istener(){ 
public void actionPerformed( 

ActionEvent event){ 



spostaFinestraQ; 



»); 



t.startQ; 



} 



protected void spostaFinestraQ { 
numTremate = numTremate + 1; 



if(numTremate == 20){ 



stopTimerQ; 



numTremate = 0; 



else{ 



p = this.getLocationQ; 



switch(numTremate){ 



case 1: this.setl_ocation(p.x 



10,p.y 
break; 



case 2: this.setl_ocation(p.x + 20,p.y 
;break; 



Jl 



case 3: this.setl_ocation(p.x 



20,p.y 
;break; 



case 4: this.setl_ocation(p.x + 20,p.y 
;break; 



Jl 



case 5: this.setl_ocation(p.x 



20,p.y 
;break; 



case 6: this.setl_ocation(p.x + 20,p.y 



);break; 



case 


7: this 


.setl_ocation(p.> 


- 20,p.y 
);break; 


case 


8: this 


setLocation(p.x 


+ 20,p.y 
);break; 


case 


9: this 


.setl_ocation(p.> 


- 20,p.y 
);break; 


case 


10:this 


.setLocation(p.x 


+ 20,p.y 
);break; 


case 


ll:this 


;.setl_ocation(p.x - 20,p.y 








);break; 


case 


12:this 


.setl_ocation(p.x 


+ 20,p.y 
);break; 


case 


13:this 


setLocation(p.x 


- 20,p.y 
);break; 


case 


14:this 


setLocation(p.x 


+ 20,p.y 


);break; 


case 


15:this 


setLocation(p.x 


- 20 # p.y 
);break; 


case 


16:this 


setLocation(p.x 


+ 20,p.y 
);break; 


case 


17:this 


setl_ocation(p.x 


- 20,p.y 
);break; 


case 


18:this 


setLocation(p.x 


+ 20,p.y 
);break; 


case 


19:this 


setLocation(p.x 


- 20,p.y 
);break; 


case 


20:this 


setLocation(p.x 


+ 10,p.y 






);break;> } } 


protected void stopTimer() { 


t.stop(); } 


public static void main(String[] 


args) { 


Trema t = new Trema ();} 



http://www.ioprogrammo.it 



Aprile 2005/ 113 ► 



EXPRESS T 



Le API di Windows 
comandate da DEV C 



Il linguaggio C++ è noto 
per la sua estrema versa- 
tilità, ne è riprova la sua 
efficienza nel controllo 
delle routine primitive di 
manipolazione di oggetti 
visuali. Con le Win API è 
possibile creare, modifica- 
re, controllare ed eliminare 
tutti gli oggetti presenti in 
Windows; quindi finestre 
standard e dialogo, messa- 
ge box, menu e quant'altro. 



C++ dalla versione stan- 
dard, alle differenti versioni 
proposte dalle maggiori 
case di software consente 
un totale controllo delle 
API di Windows. In partico- 
lare, la versione con licenza 
GNU a cui facciamo riferi- 
mento, ossia DEV C++ for- 
nisce utili esempi per com- 
prendere al meglio l'utilizzo 
di tali strumenti. 
Nell'esperienza proposta 



verrà aperto e manipolato 
un progetto di esempio, 
disponibile con il compila- 
tore citato. Verrà, così, 
facilmente creata una fine- 
stra con un una barra di 
menu tipica di semplici 
applicazioni, come il note- 
pad. Ovviamente, le diverse 
voci associate saranno 
vuote o richiameranno sem- 
plici message box. In altre 
parole vedremo come sia 



possibile costruire una 
struttura di finestra che 
contenga dei menu, facile 
da personalizzare e da 
associare all'applicazione 
che il programmatore inten- 
de sviluppare. L'insieme dei 
file che si richiameranno 
fanno parte di un unico 
progetto. La radice dei pro- 
grammi (che richiama gli 
altri) sarà main.cpp. 

Fabio Grimaldi 



APRI PROGETTO FILE... 




HDev-C ++ 4.9.9.0 




File Modifica Cerca Visualizza PrH 


Nuovo ► 1 


(|]] Apri Progetto o File. . . Ctrl+O 

vi 


H Salva Ctrl+5 
| 5alvaCome... Ctrl+F12 
| 5alva il Progetto come. . . 

^ Salva Tutto 


J| Chiudi Alt+F4 
Chiudi Tutto 
Chiudi Progetto 



Dopo aver lanciato DEV C++ che comprende oltre al 
compilatore un gradevole IDE (fortemente personaliz- 
zabile) e un potente debugger, si aprirà il file di esem- 
pio. Per farlo bisogna accedere al menu file e selezio- 
nare la voce apri progetto o file. Quindi, selezionare 
l'esempio che si presta allo scopo. 



t2> LA MANIPOLAZIONE 
DELLE API 



Apri il File 








Cerca in: 


^ WinMenu ^| 






Là 

Documenti 
recenti 

m 


Inji nnain 
B main 
jjUsrc 
1 WinMenu 



L'esempio che si intende testare, ed eventualmente 
manipolare, si trova sotto la cartella DEV-Cpp> 
Exemples> WinMenu. Per cominciare si può caricare 
WinMenu.dev, in automatico nella parte sinistra del- 
l'ambiente apparirà l'intero progetto, nella tipica 
struttura ad albero (come esplora risorse, per inten- 
derci). Si possono osservare tutti i componenti del 
progetto di esempio. 



3> APERTURA E COMPILAZIONE 
DEL FILE MAIN.CPP 



Progetto | Classi | Debug | main.cpp | 



1 



Windows e>: 
Resources 
main.cpp 
main.h 



# include <windows.h> 
^include "main.h" 

/* Declare WindowsPr^ 
LRESULT CÀLLBACK Uinc 
/* Make the classnarm 
char szClassNsme [] 
HINSTANCE hThisInstai 

int WINAPI UinHain(H: 



Dall'insieme di file presenti nel progetto si seleziona 
main.cpp. Successivamente, dal menu eseguisi sce- 
glie la voce Compila & Esegui, come si può notare 
dall'icona riportata al fianco, la stessa cosa si può ot- 
tenere cliccando sull'apposito tasto nella barra degli 
strumenti. In automatico si produrrà il file eseguibile 
che viene anche lanciato. 



t4> OSSERVIAMO IL RISULTATO 
OTTENUTO 



Windows Example 



File Edit Help 



Undo 



Cut Shift+Del 
Copy Ctrl+Ins 
Paste 5hift+Ins 



Il risultato ottenuto è una finestra con barra di menu. 
Con le tre voci file, edit e help. Ognuna contenente 
sottomenu. L'applicazione sviluppata è una struttura, 
per cui ad ognuna delle voci presenti non è associato 
alcuna routine, se non semplici message box. Come 
passo successivo si può provare a modificare la fine- 
stra ottenuta. 



MANIPOLANDO IL FILE 
RSRC.RC 



501 MENU 




BEGIN 




POPUP "SFile' 




BEGIN 




MEHUIIEH 


"SNuovo", IDH FILENEW 


MEHUITEM 


"SÀpri...", IDH FILEOPEN 


HEHUITEM 


"SSalva", IDH FILESAVE 


MEHUITEM 


"Salva Scome...", IDH FILESÀVEÀS 


MEHUITEM 


SEPARATOR 


MEHUITEM 


"S Stampa. .. ", IDHFILEPRINT 


MEHUITEM 


"Slmposta pagina...", IDH FILEPAGESETUP 


MEHUITEM 


"ISmposta stampante...", IDH FILEPRINTSETUP 


MEHUITEM 


SEPARATOR 


MEHUITEM 


"EEsci", IDH FILEEXIT 


END 





Un modo per personalizzare l'applicazione è manipo- 
lare il file delle risorse. Come esercizio proviamo a 
tradurre il menu file in italiano. Dal progetto selezio- 
niamo il file rsrc.rc ci posizioniamo nel codice alla 
funzione associata al menu file e sostituiamo tutte le 
parole con la traduzione italiana (open con apri, new 
con /7^yoi/o e così via). 



ECCO IL NUOVO RISULTATO 
OTTENUTO 



Windows Example 



File Edit Help 



Nuovo 

Apri... 

5alva 

5alva come... 



5tampa... 
Imposta pagina... 
Imposta stampante.. 



Esci 



Il nuovo risultato ottenuto è sostanzialmente simile al 
precedente, è la versione italiana. Sono disponibili an- 
che gli accessi accelerati, attraverso la contempora- 
nea pressione del tasto ALT con l'iniziale della voce, o 
comunque con la lettera preceduta dal simbolo & (in 
fase di costruzione del menu) come specificato nel co- 
dice al passo precedente. 



► 114 /Aprile 2005 



http://www.ioprogrammo.it 



Grafica ■ T EXPRESS 



Una ToolBar nelle tue applicazioni 
Con Visual Studio .NET e un attimo! 



Benché sia presente nella 
stragrande maggioranza 
delle applicazioni commer- 
ciale, la toolbar è la cene- 
rentola delle applicazioni 
sviluppate per uso persona- 
le. In questa occasione ci 
ripromettiamo di mostrare 
quanto sia semplice e 
"divertente" creare un tool- 
bar con Visual Studio. La 



maggior parte delle opera- 
zioni sono visuali e si ridu- 
cono a un drag&drop, men- 
tre la parte di programma- 
zione si limita a definire le 
operazioni da associare alla 
pressione di vari tasti della 
toolbar. Vedrete che il lavoro 
da fare si può dividere in 
due parti: la definizione 
della barra vera e propria e 



l'organizzazione delle imma- 
gini da associare ai singoli 
pulsanti. A questo proposi- 
to, ci sono moltissime risor- 
se Web che mettono a 
disposizione, gratuitamente, 
immagini per le icone. Date 
un'occhiata alla directory di 
Google: Computers > 
Software > Desktop 
Customization > Utilities > 



Icons. Seguendo il tutorial, 
arealizzaremo una barra 
risulterà dall'aspetto profes- 
sionale e perfettamente in 
linea con gli standard 
Microsoft. Insomma, non 
avete più scuse: è il 
momenti sistemare una 
barra di pulsanti nelle 
vostre applicazioni. 

Raffaele del Monaco 



ti > PREPARIAMO LA FORM 
PER IL NUOVO PROGETTO 



File Modifica Visuali 


««<, D- 




UH 




iP-!tai-B»B0| l Use «• « 
Ift|l= * =1 | W * !Ei|Eft 50 ffl; 


-|©a 


%%, 


Casella degli strumenti 4 X 


Pagina n,r, 


e Forml.cs [Progettazione] | 




« I. X 


Ddf™ 


mani wmass?n 


1 










m ImageList 
fi HelpProvider 
^ ToolTip 

mZZ ™ 














S Slattar 

Jl Fil log 

,1, , ,1 ! 

H colorDialog 
@ PrlntDialtjg 




































:lri hh " ' h ' * r " J,J 


ante la generazione 




* X 



Avviamo Visual Studio e creiamo una nuova applica- 
zione C#, io l'ho battezzata ToolB, a voi la scelta del 
nome che preferite! 

Dalla toolbox, trasciniamo una ToolBareó una Image- 
List sulla form. 



t2> SCEGLIAMO LE IMMAGINI 
TRA QUELLE PRESENTI SU HD 



Pk pi-lei :; Systerr C'i 3wing,Bitmap: 



E 


H PhysicalDirnensior 


;ight=16) 


| PixelFornnat 


IbppArgb 


HRawForrmat 


Icon 


Hsize 


16; 16 


VerticalResolution 


96 





J 



Tra le proprietà della ImageList, selezioniamo Images 
e, nella scheda che appare, andiamo ad aggiungere le 
immagini che andranno associate ai pulsanti della 
toolbar. 

Il pulsante Aggiungi consentirà di indicare la posizio- 
ne dei relativi file. 



<3 J ASSOCIAMO LA TOOLBAR 
ALLA I.AGELIST 



< 5 UN PO' DI CODICE 




Selezioniamo la ToolBare, nel pannello proprietà, an- 
diamo alla voce ImageList. Dal relativo menu a disce- 
sa, indichiamo il nome della ImageListl cioè quella 
che abbiamo appena riempito di immagini. Andiamo 
alla voce Buttons e, con un clic sul pulsante dei tre 
puntini, si aprirà una maschera che ci consentirà di 
aggiungere tutti i pulsanti che vogliamo alla nostra 
ToolBar. Per ogni pulsante, basta un clic su Aggiungi. 



<4 UN'IMMAGINE PER OGNI 
PULSANTERI 



^^ 





Proprietà toolBarBut 


on3: 




E 


nicPropertii 


E Dati 


Tag 




E Proc 




(Name) 


toolBarButton3 




Modifiers 


Private 










DropDownMenu 


(nessuno) 




Enabled 


True 




PartialPush 


□ (nessuno) J 




n o 




Pushed — | i 




B & 




Text —j,^^,^^^ 




ToolTipText 




Visible 


|True 







Sempre restando nell'editor di ToolBarButton, per ogni 
pulsante possiamo selezionare l'immagine associata, 
scelta dalla ImageListl. È sufficiente andare a sele- 
zionare l'immagine che ci interessa dal menu a disce- 
sa della proprietà Imagelndexdì ciascun pulsante. La 
proprietà Text permette invece di specificare il testo 
che accompagna ogni pulsante. 



«fTodBat 


est.Forml J |s*toclBarl_ButonCfck( t ,t.j 6 







Dindon. Fora ToolE= entl^s'e') 


senOer, System ^ 




12 3 


if ( e.Button - toolBarButtonl 


» 




12 6 


H essa B eBo*. 3 how, "Cliccato , 


1 pulsante H»,; 




128 


if , e.Button == toolBarButton2 


) 






} — ~< '— > 


1 pulsante 2.",; 




134 


if ( e.Button == toolBarButton3 


) 




13 6 


HessageBox.Showf "Cliccato i 


1 pulsante 3!"); 



Non resta che aggiungere un gestore per l'evento di clic 
su ogni pulsante. Come al solito, Visual Studio .NET 
rende banale questa operazione: un doppio clic sulla 
tool bar e verrà generato il codice-cornice, in cui defi- 
nire le azioni da compiere per ogni pulsante. Nel- 
l'esempio apriamo un box differente per ogni pulsante. 



<6> LA NOSTRA APPLICAZIONE 



US 



e/ 

Apri 



Salva 



Ci 

Apri Speciale 




■!? Funii'l 



Ci 



Salva 



a 

Apri Speciale | 



|clicca qui per aprire un documento già esistente | 



Ecco il risultato dei nostri sforzi... un po' spartano, 
per la verità! In figura, trovate anche una tooltip a 
fianco del primo pulsante. Per attivarla, è sufficiente 
selezionare l'omonima voce nelle proprietà di ogni 
pulsante e indicare il testo che si vuol far apparire. 



http://www.ioprogrammo.it 



Aprile 2005/ 115 ► 



EXPRESS T 



Impariamo a costruire un Web 
Service con Visual Studio .NET 



La piattaforma .NET, già 
dal nome, rivela la sua 
stretta voglia di Internet. È 
innegabile che la program- 
mazione per il Web ed in 
particolare per i Web 
Services abbia ricevuto un 
notevole impulso da II 'affer- 
marsi della piattaforma 



Microsoft. La semplicità 
con cui è possibile creare e 
consumare servizi Web gra- 
zie a .NET e a Visual Studio 
lasciò molti di noi a dir 
poco impressionati. Eppure, 
forse proprio per l'estrema 
semplicità della "messa in 
opera" di un Servizio Web, 



se ne discute sempre poco. 
Lo si dà per scontato. C'è il 
Wizard, è necessario MS, 
non ci si deve preoccupare 
di nulla... così viene spesso 
liquidata la questione. Non 
sulle pagine di 
ioProgrammo, ovviamente! 
Torniamo dunque su una 



argomento che in altre 
occasioni e con maggiore 
urgenza abbiamo trattato: 
prendetelo come un "richia- 
mino" in forma di Express 
per metter su un Web 
Service senza perdere la 
testa. 

Raffaele del Monaco 



<1> UN MAGO PER OGNI 
ESIGENZA 



Tipi progetto 



[rrjìl 



| Progetti di Visi 

- _J Progetti di Visual C# 






m 


SU 


m 


U 


| Xamlo! ii 










Libreria di 




Q Progetti di Visual J# 






:.er Windows 




control. 


LJ 


+ _| Progetti di Visual C++ 














i+.Q Progetti di Microsoft Offi 
_| Progetti di installazione e 


distribuì :: : 




gii 


# 


♦ 




+ U Altri progetti 






AppL. il 


--PllL l ,.- 






Ù Soluzioni di Visual Studio 






per Smart... 


WebASP.MEl 




k 


roqel f la i .■■ 


zi Web XML da 


. li~=!c t-= Eh : spn' :=-ijrn 







Nome: | WebServicel 


Percorso: | http://localhost/Web5ervicel _rj Sfoglia.,, | 
'di soluzione 

: progetto ,,'errà creato ir http://lccàhost/WebSe ./ire:. 



E 



J_ 



J_ 



Abbiamo Visual Studio .NET aperto. Possiamo non uti- 
lizzare l'immancabile wizard? Come al solito: apriamo 
un nuovo progetto, indichiamo nome e posizione, e 
specifichiamo che sarà un servizio Web. 



HELLO WORLD COME 
SERVIZIO WEB 

public Servicelo 

{ 

//CODEGEN: chiamata richiesta da Progettazione 
servizi Web ASP.NET. 

InitializeComponentQ; 

> 

// [WebMethod] 

// public strinq HelloWorldQ 

IJA 

Il return "Hello World"; 

//} 

Le informazioni relative a nome e posizione, sono 
sufficienti a Visual Studio per generare il codice di 
un semplice Web Service, pronto per essere interro- 
gato. Quello riportato sopra è proprio una parte del 
codice generato: come vedete, è sufficiente elimina- 
re il commento alle righe che definiscono il metodo 
HelloWorldO per avere subito attivo il metodo. 
Questo scheletro non é certo funzionale alla produ- 
zione di un web service efficace, ma l'esempio evi- 
denzia come Visual Studio.NET sia stato concepito 
proprio per favorire lo sviluppo di questa tecnica. 



<3> IMPOSTIAMO I METODI 

[WebMethod] 

public strinq Saluta(Strinq strMyName) 

{ 
return "Ciao" + strMyName; 



<5: AVVIAMO IL SERVIZIO 



> 

[WebMethod] 
public strinq ChiSeiQ 



{ 



return "Sono il tuo primo WS!"; 



} 



Ovviamente a noi non basta avere un metodo che, 
senza accettare parametri, ci mandi un bel saluto. 
Modifichiamo allora il codice, così come proposto 
sopra: due metodi pubblici, di cui il primo accetta 
un parametro e ritorna un valore. Notate che i meto- 
di che vogliamo siano richiamabili come servici 
Web, oltre che pubblici, devono essere preceduti 
dalla dichiarazione [WebMethod]. 
Più facile di così... 



<4> DEFINIAMO NOME 
E DESCRIZIONE 

[WebService( 

Namespace="http://ioproqrammo.it/" r 

Name="ll mio primo Web Service con .NET", 

Description="Un servizio semplice semplice da 

testare subito" 

)] 

Beh, non ci crederete, ma il Web Service è presso- 
ché completo e già pronto per funzionare. Manca 
giusto qualcosa che ne rendano facile la fruizione 
anche a chi non ne conosce la struttura. Le righe di 
codice presentate sopra vanno aggiunte subito 
prima della dichiarazione del servizio web (public 
class Serviceli. 

Come vedete, abbiamo dichiarato un Namespace, 
in modo da rendere univoca l'identificazione del 
servizio, e abbiamo impostato nome e descrizione 
per rendere più chiara la finalità e la modalità di 
utilizzo a chi dovrà interrogare il servizio. 



6 JL j-j-jju jjJ'jjjjli V'/bij 'Jby/fcb l;ujj a IiT jSjp/jzjej 'i'tbb - wiitrrjsufi J 


„JJj 


; File Modifica Strumenti ? 


# 


ì] \*H & J-* Cerca "ù: Preferiti 




. htto uk-.dn.J ''■.'/..-tdi-v. KcUSf ».t ! .d.-i.i 


Jgvai 



Il mio primo Web Service con .NET 



ìj da testare subito 

di seguito. Per 



• ChiSei 

• Saluta 



Operazione e ;mp!er i ì 



Intr iinet ocale 



Cliccando su F5, Visual Studio compilerà e avvierà il 
servizio. Contemporaneamente, verrà avviata un'i- 
stanza di Explorer che mostrerà la pagina http-J/lo- 
calhost/WebServicel/Servicel.asmx, ovverosia l'indi- 
rizzo del nostro servizio. Vedete che sono presenti tre 
link: il primo punta alla file WSDL con la descrizione 
del servizio, mentre glil altri due consentono di prova- 
re i metodi attraverso il browser. 



<6> 


UN TEST DIRETTO 




Saluta 

Test 

Per esegi. 


ire il test del ndo il protoc 


ilio HTTP POST, 




Parametro Valore 


strMylMa 


ne: | Fabio| 


1 






| Richiama | 










<?xml version-'l.O" encoding="utf-8" ?> 

<string xmlns="http://ioprogrammo.it/">CiaoFabio</string> 



Per provare il servizio è sufficiente cliccare su uno 
dei due link proposti. Ad esempio, clicchiamo su Sa- 
luta. La pagina Web che si aprirà consentirà di in- 
serire un nome: in realtà stiamo simulando, via 
Web, il passaggio di parametri che dovrà avvenire 
da codice. Inserendo una stringa e cliccando sul 
pulsante Richiama, otterremo il documento XML che 
rappresenta la risposta del nostro metodo all'invo- 
cazione. Tutti i meccanismi di scambio dati SOAP e 
quant'altro rimangono nascosti al programmatore 
che non si deve preoccupare di implementare la 
parte più a basso livello del codice. 



► 116 /Aprile 2005 



http://www.ioprogrammo.it 



Database ■ T EXPRESS 



Connettersi a un DB in ASP 
in ambiente Dreamweaver 



LJuso dei Database nel- 
, l'ambito del web è sem- 
pre più frequente. Gli 
ambienti visuali di sviluppo 
come Front Page e 
Macromedia sono molto usati 
per la creazione di semplici 
pagine html. Accanto alle più 
frequenti funzioni per la crea- 
zione di siti web tali software 
mettono a disposizione dei 
programmatori utili tools per 
la manipolazione di database; 



ad esempio mediante la 
metodologia ASP (active ser- 
ver pages). Come tutti i lin- 
guaggi ASP può essere pro- 
grammato con il più spartano 
degli editor. Innegabili però, 
sono i vantaggi che si posso- 
no avere con l'uso di un 
ambiente di sviluppo visuale 
e integrato come 
Macromedia Dreamweaver. 
Esso da un lato è ottimo stru- 
mento per lo creazione di 



pagine html, pronte a essere 
pubblicate sul web, dall'altro 
si presta alle soluzioni di 
moltissime situazioni correla- 
te allo sviluppo su piattafor- 
me web. Nel caso specifico 
integra ottimamente ASP e la 
tecnologia sottesa all'uso e 
alla manipolazione di DB da 
web. Purché abbiate un ser- 
ver web (Pws, Apache o MS) 
installato su pc potrete in 
pochi passi connettere un DB 



al sito in costruzione. La con- 
nessione mediante ODBC è 
lo stadio preliminare (utiliz- 
zando il software in esame). 
Una volta connesso il DB al 
server mediante ASP è possi- 
bile comandarlo semplice- 
mente programmando. Passo 
zero per il raggiungimento 
dell'obbiettivo è aprire il 
software sopraccitato, si trat- 
ta della versione MX2004. 

Fabio Grimaldi 



<1> AVVIO DEL SOFTWARE 
E CREAZIONE DEL SITO WEB 



idi Sito Finestra 
Gestisci siti.,. 



■ 



Annulla ritiro 
Individua nel sito 



Ctrl+Maiusc+D 
Ctrl+Alt+Maiusc+D 
Ctrl+Maiusc+U 
Ctrl+Alt+Maiusc+U 



Rapporti.,. 

Controlla tut to Ctrl+F8 

Cambia tutti "iti del sito,., 

Avanzate 



5È ASP JavaScript 



(^ Strutture di pagin 



Dopo aver avviato Macromedia Dreamweaver defi- 
niamo un nuovo sito dal omonimo menu. 
Selezionando gestisci sito appare una nuova fine- 
stra di dialogo dove sono presenti tutti i siti che si 
stanno sviluppando. La lista è vuota se è la prima 
volta che utilizziamo il software. 
Scegliamo la voce nuovo. 

<2> CREAZIONE GUIDATA DELLE 
CARATTERISTICHE DEL SITO 



a ne del sito per Libri 



Generali | Avanzate , 



Definizione del sito 



Si intende utilizzai e una tecnologia server come Coìdrusion, ASP.NtT, A5P, JSP o PHP" 
'_ ' No, non voglii nologia server. 

Sì, voglio ogia server. 

l'i i- . - 1 1 li a- server? 



|0 



La creazione guidata del sito e delle sue caratteri- 
stiche è accompagnata da svariati passi associa- 
ti alla stessa finestra di dialogo. 
Dopo aver immesso il nome del sito (chiamato Libri 
come l'omonimo DB), cliccando sua avanti viene 
chiesto se si vuole utilizzare la tecnologia server. 
Possiamo scegliere uno dei vari linguaggi proposti. 
In questo caso desideriamo I avorare con asp ; , per- 
ciò selezioniamo ASP Javascript. 



<3> SCELTA DELL'AREA DI 
LAVORO COME CARTELLA LOCALE 




Come sì intende favolare su file disiente io sviluppo' 5 
Eseguend 

■■V si i ili . I :,'.,: 

"i. fini- inHr lijf -in = ' ir .fi ir» ni ,-, ,= ri'-f<-. i s,= r > -«-.=,!■ = ri ■- !-• = .= -,- il,= 



i; : il :ornp'.,tei de •- . . _ e 



1 : Hi I : ' I ili 



Lo sviluppo può essere fatto provando direttamen- 
te i file su di un server collegato in remoto al no- 
stro PC. 

Noi optiamo per la strada più semplice ed effi- 
ciente in fase di primo sviluppo. 
Scegliamo la prima voce: modifiche e prove local- 
mente su una cartella a nostra scelta. C:\inet- 
pub\wwwrootè il default a cui fa riferimento US. 



*4> COMUNICAZIONE TRA LURL 
E IL SERVER DI PROVA 



ine del sito pei Libri 



Generali Avanzate | 



Definizione del sito 



Quale URL deve essere utilizzalo per aceedeie ai 
http: //localhost/librì/ | 

sempio i'iRp A''GeivesUrio/'Cari:e!laPtirieipale/ 



i cariella principale del sto? 



La comunicazione tra URL e il server di prova av- 
viene attraverso il conosciuto protocollo HTTP. Si 
rende necessario un indirizzo che per default è 
http-J/localhost/libri. 

Manteniamo tale indirizzo e dopo averlo testato 
con un apposito click su prova URL chiudiamo la 
procedura di creazione del sito. 



<5> CONFIGURAZIONE DEL DSN 
(DATASOURCENAME) 



ronfigli razione ODBC poi Microsoft Access 


\m 




OK 


righe dati: |DB Libri 


Descrizione: L'È ci n'e'irneuici 


Annulla 


Database: C:\...\n_8 i ì iblio.mdb 
Seleziona... Crea... Ripristina... Compatta... 


' 1 


Avanzate... 






Opzioni » 


G Nessuno 
C Database: 

Database di sistema... 







Dal menu elabora o direttamente sul segno + dell'ap- 
posita finestra applicazioni ASP definiamo il DNS. Con 
questo procedimento si legherà il DB precedentemen- 
te creato in Access (ci si può connettere anche ad altri 
formati di DB). Dalla voce seleziona scegliere il file 
mdb che si intende connettere al sito in fase di svi- 
luppo (nel esempiolibri.mdb). 

(6> DEFINIZIONE 
DELLA CONNESSIONE 






Nella successiva finestra di dialogo tra i DSN presen- 
ti oltre al DB di prova apparirà quello appena connes- 
so. Si nomina la nuova connessione LinkLibri e si ter- 
mina la fase prefissata. Cliccando sul tasto prova si 
potrà verificare se l'operazione è avvenuta corretta- 
mente. Adesso il DB è pronto ad essere usato nel sito. 
Tutto é pronto. Continuando a lavorare con Dream- 
weaver avrete adesso a disposizione un database da 
potere utilizzare in modo del tutto visuale, ad esempio 
trascinando una datagrid sulla pagin, automatica- 
mente verrà generato il codice che consente di visua- 
lizare il contenuto del database. 



http://www.ioprogrammo.it 



Aprile 2005/ 117 ► 



Database ■ T EXPRESS 



Connettersi a un DB in ASP 
in ambiente Dreamweaver 



LJuso dei Database nel- 
, l'ambito del web è sem- 
pre più frequente. Gli 
ambienti visuali di sviluppo 
come Front Page e 
Macromedia sono molto usati 
per la creazione di semplici 
pagine html. Accanto alle più 
frequenti funzioni per la crea- 
zione di siti web tali software 
mettono a disposizione dei 
programmatori utili tools per 
la manipolazione di database; 



ad esempio mediante la 
metodologia ASP (active ser- 
ver pages). Come tutti i lin- 
guaggi ASP può essere pro- 
grammato con il più spartano 
degli editor. Innegabili però, 
sono i vantaggi che si posso- 
no avere con l'uso di un 
ambiente di sviluppo visuale 
e integrato come 
Macromedia Dreamweaver. 
Esso da un lato è ottimo stru- 
mento per lo creazione di 



pagine html, pronte a essere 
pubblicate sul web, dall'altro 
si presta alle soluzioni di 
moltissime situazioni correla- 
te allo sviluppo su piattafor- 
me web. Nel caso specifico 
integra ottimamente ASP e la 
tecnologia sottesa all'uso e 
alla manipolazione di DB da 
web. Purché abbiate un ser- 
ver web (Pws, Apache o MS) 
installato su pc potrete in 
pochi passi connettere un DB 



al sito in costruzione. La con- 
nessione mediante ODBC è 
lo stadio preliminare (utiliz- 
zando il software in esame). 
Una volta connesso il DB al 
server mediante ASP è possi- 
bile comandarlo semplice- 
mente programmando. Passo 
zero per il raggiungimento 
dell'obbiettivo è aprire il 
software sopraccitato, si trat- 
ta della versione MX2004. 

Fabio Grimaldi 



<1> AVVIO DEL SOFTWARE 
E CREAZIONE DEL SITO WEB 



idi Sito Finestra 
Gestisci siti.,. 



■ 



Annulla ritiro 
Individua nel sito 



Ctrl+Maiusc+D 
Ctrl+Alt+Maiusc+D 
Ctrl+Maiusc+U 
Ctrl+Alt+Maiusc+U 



Rapporti.,. 

Controlla tut to Ctrl+F8 

Cambia tutti "iti del sito,., 

Avanzate 



5È ASP JavaScript 



(^ Strutture di pagin 



Dopo aver avviato Macromedia Dreamweaver defi- 
niamo un nuovo sito dal omonimo menu. 
Selezionando gestisci sito appare una nuova fine- 
stra di dialogo dove sono presenti tutti i siti che si 
stanno sviluppando. La lista è vuota se è la prima 
volta che utilizziamo il software. 
Scegliamo la voce nuovo. 

<2> CREAZIONE GUIDATA DELLE 
CARATTERISTICHE DEL SITO 



a ne del sito per Libri 



Generali | Avanzate , 



Definizione del sito 



Si intende utilizzai e una tecnologia server come Coìdrusion, ASP.NtT, A5P, JSP o PHP" 
'_ ' No, non voglii nologia server. 

Sì, voglio ogia server. 

l'i i- . - 1 1 li a- server? 



|0 



La creazione guidata del sito e delle sue caratteri- 
stiche è accompagnata da svariati passi associa- 
ti alla stessa finestra di dialogo. 
Dopo aver immesso il nome del sito (chiamato Libri 
come l'omonimo DB), cliccando sua avanti viene 
chiesto se si vuole utilizzare la tecnologia server. 
Possiamo scegliere uno dei vari linguaggi proposti. 
In questo caso desideriamo I avorare con asp ; , per- 
ciò selezioniamo ASP Javascript. 



<3> SCELTA DELL'AREA DI 
LAVORO COME CARTELLA LOCALE 




Come sì intende favolare su file disiente io sviluppo' 5 
Eseguend 

■■V si i ili . I :,'.,: 

"i. fini- inHr lijf -in = ' ir .fi ir» ni ,-, ,= ri'-f<-. i s,= r > -«-.=,!■ = ri ■- !-• = .= -,- il,= 



i; : il :ornp'.,tei de •- . . _ e 



1 : Hi I : ' I ili 



Lo sviluppo può essere fatto provando direttamen- 
te i file su di un server collegato in remoto al no- 
stro PC. 

Noi optiamo per la strada più semplice ed effi- 
ciente in fase di primo sviluppo. 
Scegliamo la prima voce: modifiche e prove local- 
mente su una cartella a nostra scelta. C:\inet- 
pub\wwwrootè il default a cui fa riferimento US. 



*4> COMUNICAZIONE TRA LURL 
E IL SERVER DI PROVA 



ine del sito pei Libri 



Generali Avanzate | 



Definizione del sito 



Quale URL deve essere utilizzalo per aceedeie ai 
http: //localhost/librì/ | 

sempio i'iRp A''GeivesUrio/'Cari:e!laPtirieipale/ 



i cariella principale del sto? 



La comunicazione tra URL e il server di prova av- 
viene attraverso il conosciuto protocollo HTTP. Si 
rende necessario un indirizzo che per default è 
http-J/localhost/libri. 

Manteniamo tale indirizzo e dopo averlo testato 
con un apposito click su prova URL chiudiamo la 
procedura di creazione del sito. 



<5> CONFIGURAZIONE DEL DSN 
(DATASOURCENAME) 



ronfigli razione ODBC poi Microsoft Access 


\m 




OK 


righe dati: |DB Libri 


Descrizione: L'È ci n'e'irneuici 


Annulla 


Database: C:\...\n_8 i ì iblio.mdb 
Seleziona... Crea... Ripristina... Compatta... 


' 1 


Avanzate... 






Opzioni » 


G Nessuno 
C Database: 

Database di sistema... 







Dal menu elabora o direttamente sul segno + dell'ap- 
posita finestra applicazioni ASP definiamo il DNS. Con 
questo procedimento si legherà il DB precedentemen- 
te creato in Access (ci si può connettere anche ad altri 
formati di DB). Dalla voce seleziona scegliere il file 
mdb che si intende connettere al sito in fase di svi- 
luppo (nel esempiolibri.mdb). 

(6> DEFINIZIONE 
DELLA CONNESSIONE 






Nella successiva finestra di dialogo tra i DSN presen- 
ti oltre al DB di prova apparirà quello appena connes- 
so. Si nomina la nuova connessione LinkLibri e si ter- 
mina la fase prefissata. Cliccando sul tasto prova si 
potrà verificare se l'operazione è avvenuta corretta- 
mente. Adesso il DB è pronto ad essere usato nel sito. 
Tutto é pronto. Continuando a lavorare con Dream- 
weaver avrete adesso a disposizione un database da 
potere utilizzare in modo del tutto visuale, ad esempio 
trascinando una datagrid sulla pagin, automatica- 
mente verrà generato il codice che consente di visua- 
lizare il contenuto del database. 



http://www.ioprogrammo.it 



Aprile 2005/ 117 ► 



SOFTWARE SUL CD T ■ Tool di sviluppo 



ÉV7I 



SUL CD 



ioR 



ioprogrammo.it 

ROGRAMMO n . 90 



wiAim-ìimi,n\i4fiii-ìmviìii- 



VB.NET 

ASP.NET 

FLASH 

JAVA 



"BUILDER 



PHP 5.0.3 

■ DEV-PHP 2.0.9 
I DEV C++ 5 BETA 9 
I ULTIMATE C++ 



SHARPDEVELOP 1.1 



Apache 1.3.33/2.0.52 

Uno dei server Web più usati 
al mondo 

Un indispensabile ormai. ioProgrammo 

10 ripropone spessissimo fornendovi 
sempre le versioni più aggiornate. Viene 
utilizzato in tutti i problemi che riguarda- 
no un'integrazione con il Web. 

Se avete bisogno di un server Web per 
provare le vostre applicazioni Web, oppu- 
re da usare in sistemi di produzione, Apa- 
che è quello che fa per voi. 
Directory: /Apache/ 

PHP 5.0.3 

11 linguaggio di scripting per il web 

Ormai PHP lo conoscete tutti, e se non lo 
avete mai usato, sicuramente vi sarà capi- 
tato di accedere a qualche sito web svilup- 
pato con PHP Saprete dunque perciò che è 
un linguaggio di scripting particolarmente 
utilizzato per sviluppare Web Application. 
Incredibilmente potente, fa della comple- 
tezza del linguaggio, della facilità di ap- 
prendimento, della capacità di integrarsi 
con applicazioni di Dababase i suoi punti 



di forza. 
Directory: /PHP 

Python 2.4 

Un linguaggio orientato 

agli oggetti con tanto di supporto 

a classi ed ereditarietà 

Viene usato in una varietà di applicazioni. 
A quanto pare è largamente utizzato ad 
esempio da Google per lo sviluppo delle lo- 
ro applicazioni. Si caratterizza per la ge- 
stione dinamica della memoria, per l'ele- 
vata portabilità, per la curva di apprendi- 
mento relativamente breve. Un linguaggio 
di programmazione di cui sentiremo par- 
lare a lungo. 
Directory: /Python 

Hibernate 3.0 

Il framework per gestire 
la persistenza dei dati 

Sicuramente avrete già avuto occasione di 
notare che ioProgrammo comincia a dare 
spazio a Hibernate. Si tratta di un Frame- 
work molto interessante, di cui sicuramen- 
te parleremo in profondità. Lo scopo prin- 



cipale è garantire una corrispondenza fra il 
modello ad oggetti dei programmi che svi- 
luppiamo e lo schema dei database sotto- 
stanti. 
Directory /Hibernate 

MySQL 4.1.9 

Il server di database OpenSource 
più diffuso al mondo 

MySQL è un indispensabile. ioProgrammo 
ogni mese vi offre la versione aggiornata. Si 
tratta del server di database fondamentale 
per la maggior parte delle applicazioni 
Internet scritte in PHP Ma è difussissimo 
anche per le applicazioni Standalone e gra- 
zie ai nuovi connector comincia a essere 
usato anche dagli sviluppatori .NET 
Directory /Mysql 

Sqlite 2.8.15 

Il nuovo database Bundled 
con PHP5 

Come molti di voi già sapranno, il nuovo 
PHP5 ha spostato l'attenzione dal suppor- 
to a MySQL a quello a SQLite. SQLite è un 
database piccolo e leggero che consente di 



Damn Small Linux 



Linux in 50MB 

Si tratta di una versione 
live dell'ormai noto Linux. 
Per Live si intende che 
potere masterizzare la trac- 
cia ISO che distribuiamo in 
questo numero di 
ioProgrammo ed effettuare 
il boot del sistema operati- 
vo direttamente dal 
CDRom senza dovere scri- 
vere neanche un file 
sull'Hard Disk. 
Nononstante questo, le 
prestazioni di Damn Small 
sono buone, potete tran- 
quillamente configurare la 
rete, navigare con FireFox, 



persino leggere la posta. 
Nei 50Mb in questione non 
è stato possibile concentra- 
re un intero compilatore o 
un ambiente di sviluppo, 
tuttavia rimane una buona 
opportunità per i program- 
matori che desiderano 
incominciare a prendere 
confidenza con l'ambiente, 
magari per sviluppare 
applicazioni multipiattafor- 
ma. Nello screenshot nota- 
te come abbiamo fatto 
girare la Damn Small in 
una finestra di Windows 
tramite Virtual PC. Con un 




sistema abbastanza ben 
dotato si riescono a tenere 
in piedi contemporanea- 



mente i due sistemi senza 
grande difficoltà. 

Directory :/damnsma 



► 118 /Aprile 2005 



http://www.ioprogrammo.it 



Tool di sviluppo ■ T SOFTWARE SUL CD 



lavorare su archivi di dati pur non doven- 
do installare un server. Per molti versi lo si 
può paragonare ad Access male sue carat- 
teristiche lo rendono particolarmente ver- 
satile e compatibile con la maggior parte 
delle web application scritte in PHP II 
software che vi presentiamo è un piccolo 
client a linea di comando, utile per gestire, 
creare tabelle e database senza dover pas- 
sare per PHP 
Directory: /Sqlite 

SharpDevelop 1.0.3.1761 

L'alternativa a Visual Studio 
a basso costo 

Microsoft senza dubbio ha modificato il 
suo modo di intendere lo sviluppo delle 
applicazioni con l'introsuzione della 
piattaforma .NET. Tuttavia lo sviluppo in 
tecnologia .NET non è una prerogativa 
dei soli ambienti targati Microsoft. 
Esistono delle pur valide alternative a 
Visual Studio se si vuole comunque svi- 
luppare in C# ad esempio oppure in 
VB.NET, SharpDevelop è una di queste. 
Visual Studio rimane sempre un am- 
biente estremamente completo colmo di 
caratteristiche che lo rendono unico, tut- 
tavia SharpDevelop rappresenta un'otti- 
ma alternativa, economica, potente, affi- 
dabile. 
Directory: /Sharpdevelop 

Tomcat 5.5.4 

Il servlet container per Java e JSP 

L'idea è molto semplice. Sviluppare in 
Java pagine Web. Ad un primo sguardo, 
Tomcat, potrebbe sembrare un normale 
Web Server. Ed in effetti è un normale 
Web Server! In grado di soddisfare le ri- 
chieste per qualunque pagina Html. In 
realtà però Tomcat è anche qualcosa in 
più. Di fatto però Tomcat offre qualcosa 
in più, ovvero la capacità di soddisfare 
richieste per applicazioni Java. Potrebbe 
sembrare complesso, in realtà lo è meno 
di quanto sembri. Immaginate Tomcat 
come un grande contenitore al cui inter- 
no ci sono altri contenitori ciascuno dei 
quali rappresenta un'applicazione Java, 
che richiamata da luogo ad una pagina 
HTML interpretabile da un browser. 
Questo consente di sviluppare pagine 
Web (JSP) utilizzando tutta la potenza 
della normale gerarchia di classi Java e la 
sintassi e il linguaggio che qualunque 
programmatore Java conosce bene. 
Directory: /tomcat 



Dev-PHP 2.0.9 

Ottimo editor PHP OpenSource 

Se state iniziando a sviluppare in PHP 
avrete bisogno di un editor. Scrivere co- 
dice con il notepad può essere un eser- 
cizio divertente, ma quando iniziate a 
scrivere script leggermente più com- 
plessi si impone la scelta di passare a un 
editor più completo. 



jboss-3.2.3_nutes-1.1.0-P.C 

JDO55-4.0.1RC1 

S E3 jdbc „ 



: ID COHUMICÀTC 






Dev-PHP Code Completion 



(stringar, string $charlist] 



"■■■>, n atray ifrrnxed 1 .]! 

I I ,.■ !■■.::. . 'v': . 

Z 



-r od ' oiimnicato [ ' Quesl 



DEV-PHP non solo è completo ma an- 
che molto potente. Dotato di code 
completion, sintax highlighting, funzio- 



nalità di ricerca avanzate ed una serie di 
tool piuttosto interessanti rappresenta 
una grande scelta per programmare in 
PHP. Inoltre è un editor straordinaria- 
mente leggero, oltre che gratuito ed 
OpenSource. 
Da non perdere! 
Directory: /DevPHP 

Irrlicht 0.7 

Sviluppare Giochi 3D potenti 
in modo semplice 

Da quando Alfredo Marroccelli ha ini- 
ziato la serie di articoli riguardanti lo 
sviluppo di Giochi 3D basati sul 3D 
Engine Irrlicht, siamo stati letteralmen- 
te sommersi dalle email dei lettori che 
si sono divertiti a programmare il pro- 
prio gioco 3D. Irrlicht è straordinaria- 
mente potente, facile da usare, intuiti- 
vo. Tanto da meritare uno spazio fisso 
nelle nostre pagine. 
Directory: /irrlicht 



Cse HTML Validator Lite V6.52 

Un validatore per le vostre pagine html 



Il Web non è più un mondo completa- 
mente selvaggio come ai suoi inizi. 
È importante produrre delle pagine 
HTML conformi agli standard, accessi- 

gsna 






-h 



Optai ; Linl-5 ì.jpgrads Nt« 



ita blue f Barasi t iteti), zed (acti- 

.or="#FFFFFF" link="#0 vlink= al] 



5 Segzave; stato i 



Q APRIAMO UN NUOVO FILE - Dal 
menu File/Open selezionamo il 
file html su cui eseguire la validazione 



bili e visualizzabili da tutti i sistemi se 
si vuole ottenere un qualche risultato 
dal proprio lavoro. Cse Validator è un 
validatore HTML. Controlla che il codi- 
ce prodotto all'interno delle vostre 
pagine sie conforme agli standard det- 
tati dal W3C consortium e vi avverte 
se avete usato qualche tag in maniera 
non corretta o se qualche link non è 
funzionante. 

Si tratta di un ottimo tool da utilizzare 
in fase di finalizzazione dei propri 
lavori. Produrre dei siti accessibili e 
conformi agli standard è decisamente 
un dovere per un buon programmato- 
re, oltre che un ottimo biglietto di pre- 
sentazione ai vostri clienti. 

Directory /csevalidator 



# 

se 

9 


e Edi 




11 


"iview Tags Drag and 


rop Options Lin 


Jpgrade Now 


-di-aS 


Validate 


F6 K 


M ft # ' # ' H Validate . 




Validate Ali 




h 




Validate StyleSheetwith 


TopStyle 


i 


I.DOCT 
<HIML 

// —? 
</ S cri 

//— > 


;.-■-.:■. ■ > 

r Xanguage= > 


Speli Check.,, 


SniF^ 


Convert Text File Format 
Quick Lowercase 
Quick Quote Tool 
Quick Strip HTML Tags 
Quick Uppercase 


., Ctrl+F9 


Tool, Options... 


Help ™th Tool S 




T type="text/javasc 


ript rr JLangu 


ige="javascript"> 



e[f]hiklmnopqstuv 






'e()). 






// —> 

</scriptxSCRIPT type="te 

var cust ornala tìì=' 730', 

</SCRIPT> 

-SCRIPT la.nguage="javi 
< SCRIPT language= 
SCRIPT type="text/jeiveisc 



:ript" language= r 'jai 



• - . . 
ipt" src=' p / ler.js" typ 

ript" languatje= r 'javascr ipt"> 









HVALIDAMO IL FILE - Dal menu 
tools scegliamo validate ali per 
ottenere la validazione 



al RISULTATI - Nella finestra in 
basso verranno evidenziati tutti 
i problemi di validazione 



http://www.ioprogrammo.it 



Aprile 2005/ 119 ^ 



SOFTWARE SUL CD T ■ Tool di sviluppo 



Smarty 2.6.7 

Il template engine per PHP 

Se avete letto il libro "imparare PHP" 
allegato alla versione Plus di ioProgram- 
mo nello scorso numero, sapete già cosa 
è Smarty e come si usa. Si tratta di un 
template engine per PHP. 
Ovvero un sistema che consente di se- 
parare la logica di programmazione da 
quella di layout. 

Sostanzialmente il web designer avrà a 
doisposizione un formato molto simile 
alFHTML per sviluppare le pagine che 
conterranno l'elaborazione delle appli- 
cazioni sviluppate con PHP. Molto co- 
modo e potente è certamente un sistema 
da utilizzare per sviluppare in modo effi- 



cace le proprie Web Application con PHP 
Directory /Smarty 

Sqlite .NET 

Un connector .NET per questo 
interessante database 

Sqlite è il nuovo database bundled con la 
versione 5 di PHP. Al di là di godere di 
questa interessante caratteristica, Sqlite 
è anche un ottimo database che può es- 
sere utilizzato in applicazioni standalo- 
ne. Gode della proprietà di essere molto 
leggero e file based, non necessità di par- 
ticolare attenzione per essere installato e 
con poche righe di codice il vostro DB 
sarà pronto. Il meccanismo è molto simi- 
le a quello di Access, il sistema di autenti- 



cazione e gestione degli utenti è infatti de- 
mandato al sistema operativo, tuttavia la 
velocità e l'affidabilità sono impressio- 
nanti. Se avete bisogno di un database 
leggero senza troppe complicazioni ma 
non volete affidarvi ad Access, Sqlite è 
quello che fa per voi. Questo connector 
per .NET vi consente di accedere a data- 
base formato Sqlite dalle vostre applica- 
zioni .NET. 
Directory: /Sqlite 

Aqua Data Studio 4.0 

Il query builder leggero 
ed efficiente 

Aqua Data Studio è un buon tool per la ge- 
stione di Dabase di diverso tipo. Supporto 



BORLAND JBUILDER 2005 FOUNDATION 



L'eccezionale ambiente di Borland per lo sviluppo Java 



Jbuilder è l'ambiente propo- 
sto da Borland per lo svilup- 
po di applicazioni Java. Come 
è tradizione di Borland si 
tratta di un ambiente incredi- 
bilmente curato nei particola- 
ri. Dotato di tutte le caratteri- 
stiche essenziali per un otti- 



mo editor Java, la versione 
Foundation ha dalla sua 
parte il costo praticamente 
nullo, dovuto alla sua licenza, 
l'uso della foundation è infat- 
ti gratuito per usi personali. 
Il software è completo e 
senza scadenza. Certo ha 



delle limitazioni rispetto alla 
versione enterprise, ad esem- 
pio non è possibile gestire i 
progetti UML, ma si tratta di 
limitazioni che comunque 
influiscono solo sulla produ- 
zione di progetti di largo 
respiro. Insomma per un pro- 



grammatore Java che si accin- 
ge a iniziare oppure per un 
programmatore Java che non 
ha necessità di sviluppare 
progetti Enterprise, la versio- 
ne Foundation è assoluta- 
mente da provare. Molto 
comodo il Visual Designer 




DUNA NUOVA APPLICAZIONE - Si 
parte del menu FilelNewl sceglien- 
do poi l'icona Application nella finestra 
di dialogo successiva 



H DIAMO UN NOME AL PROGETTO - 
Scegliamo il nome da dare al pro- 
getto indicandolo nell'apposita casella. 
Clicchiamo poi su ok 



H QUALE JAVA? - Scegliamo la 
versione di java da utilizzare, 
con JBuilder viene distribuita la 
versione 1.4 







m | Rame Tito 




0Ge 
0Ge 




eratet oo, to 0^™o a 




-sBack Nexts Finish Cancel Help 




H DIAMO UN NOME ALL' APLICAZ IO- 
NE - Scegliamo un nome per l'ap- 
plicazione, può differire da quello del 
progetto generale 



HLO SCHELETRO - Scegliamo di 
generare un'applicazione 
completa di menu, icone e status bar 



BCREAIMO EVENTUALI FILE DI CON- 
FIGURAZIONE - Se l'applicazione 
necessiterà di file di configurazioni par- 
ticolari è possibile generarli da qui 



^ 120 /Aprile 2005 



http://www.ioprogrammo.it 



Librerie e Tool di sviluppo ■ T SOFTWARE SUL CD 



Oracle, MySQL, MS SQ1 e moltissimi altri 
formati. Non è completamente visuale 
come qualcuno potrebbe aspettarsi da un 
prodotto pubblicizzato come query buil- 
der ma è dotato di alcune interessanti fun- 
zionalità che lo rendono uno strumento di 
supporto rapido ed efficiente. Ad esempio 
nonostante le vostre query debbano esse- 
re descritte manualmente, Aqua Studio è 
dotato di completion e syntax hilghligh- 
ting il che lo configura come un editor per 
il linguaggio SQL piuttosto che come un 
Rad Query builder. Se utilizzato corretta- 
mente può velocizzare di molto lo svilup- 
po di applicazioni di database. Natural- 
mente può essere utilizzato anche come 
rimpiazzo dei vari PHPMyAdmin o My- 



che consente di disegnare le form per 
trascinamento dei componenti, come 
nella migliore tradizione degli ambien- 
ti RAD, tuttavia richiede un sistema 
sufficientemente dotato per potere 
essere utilizzato con profitto. 

Directory /JbuilderFoundation 







Includerei 

Diagram reterei tram sene 



□ CARATTERISTICHE GENERALI - 
Settiamo le proprietà generali, 
per i nostri scopi andranno bene quelle 
di default 





O-BR-WB»-* - 


e- « - ì. fe * °> - B 1 - te ■ >s> - + ■ H 


■1*1»- 


leiat 


-a*— ! 




SJL^J ; 


:e»# 


r &■ 




*»;££» 


« JU» 




j^.i~ 






„ ». W.«™, hU 


«wwli»* 




*■"' ■"■" "— °- ****' 



Q PRONTI - Lo scheletro della 
nostra prima applicazione è 
pronto cliccate su Design per comple- 
tare l'interfaccia 



SqlCC anche se non trattandosi di un pro- 
dotto dedicato non è dotato di tutte le fun- 
zionalità tipiche di questi strumenti. 
Directory /Acquadatastudio 

Eclipse 3.0.1 

La piattaforma universale 
multifunzione 

Sembra un sottotitolo esagerato ed ecla- 
tante: "La piattaforma universale multifun- 
zione" ed invece Eclipse è nato proprio con 
questo scopo. A prima vista sembra un 
normale editor per programmatori Java, 
anzi molto di più che un normale editor, 
visto che ospita una serie di funzionalità 
piuttosto avanzate che vanno dal code 
completion alla syntax highlithing al refac- 
toring e che lo stanno portando a diventa- 
re uno standard proprio per Java, tuttavia è 
anche vero che Eclipse è completamente 
estensibile per mezzo di plugin, tanto che 
può essere utilizzato da programmatori 
PHP come da programmatori C++ e persi- 
no come frontend verso database etc. In- 
somma qualunque tipo di necessità voi 
abbiate, Eclipse è in grado di aiutarvi. Se 
poi siete dei programmatori Java rientra in 
quel ristretto numero di software indi- 
spensabili per gestire rapidamente il 
vostro lavoro. 
Directory: /Eclipse 

Blender 2.36 

Un modeller per oggetti 3D 

Blender non è propriamente un tool riser- 
vato ai soli programmatori, piuttosto può 
aiutare alcune categorie di programmatori 
nello sviluppo dei propri software. 




Si tratta infatti di un ambiente per lo svi- 
luppo di modelli tridimensionali. Indi- 
spensabile per chi per esempio sviluppa 
videogame gode di alcune importanti pro- 
prietà. È un prodotto GPL perciò privo di 
costi diretti, è straordinariamente potente 
e completo di tutte le caratteristiche dei 
più noti software commerciali, è in grado 
di esportare i dati in formati comprensibi- 
li dalla maggior parte degli engine 3D ivi 



compresi Irrlicht e Directx. Perciò se siete 
degli sviluppatori di videogame o se in un 
qualche modo sviluppate dei prodotti atti- 
nenti al mondo ridimensionale, Blender 
senza dubbio vi può essere utile. 
Directory: /Blender3D 

Menalto Gallery 2.0 

Una gallery fotografica pronta 
per il Web 

Siete appassionati di fotografia? Volete 
vendere online sfondi, immagini? Più sem- 
plicemente volete creare una galleria foto- 
grafica Online? Questo software è quello 
che fa per voi. Si tratta di una delle prime 
web application ad essere nate per la ge- 
stione di gallerie fotografiche sul web, per- 
ciò vanta un'esperienza notevole e tutto 
questo si riscontra nella cura dei particola- 
ri. È un software scritto in PHP che si ap- 
poggia in parte a MySQL in parte utilizza 
imagemagick oppure le GD per la gestione 
delle immagini. Sufficientemente semplice 
da installare, è facilmente integrabile in 
moltissimi CMS opensource, che anzi 
spesso e volentieri lo propongono come 
tool aggiuntivo. In ogni caso rappresenta 
un'ottima soluzione per la gestione di gal- 
lerie di immagini sul Web 
Directory: /gallery 

HSqldb 1.7.3 

Un database piuttosto potente 

Nato in sordina come prodotto OpenSour- 
ce, HSqlDB in breve tempo sta conquistan- 
do gli onori della cronaca grazie alla sua 
eccezionale velocità, semplicità d'uso e af- 
fidabilità. Si tratta di un Database comple- 
tamente scritto in Java che occupa appena 
lOOk ma che espone caratteristiche inte- 
ressanti. Sembrerebbe che proprio HSql- 
Db sia stato scelto come prodotto di base 
per lo sviluppo del nuovo applicativo di da- 
tabase che completerà la suite di OpenOf- 
fice nella sua versione 2.0. Questo testimo- 
nia anche la validità del prodotto, se ce ne 
fosse ulteriore bisogno. 
Directory /hsqldb 

TikiWiki 

Un Wiki piuttosto interessante 

Probabilmente il miglior Wiki opensource 
attualmente disponibile. Scritto in PHP 
con l'ausilio dei template di Smarty si sta 
lentamente avviando ad essere un Wiki 
esteso, cioè un wiki che integra funziona- 
lità tipiche di un Cms. Ma cosa è un wiki? 
In linea del tutto generale un wiki è un 



http://www.ioprogrammo.it 



Aprile 2005/ 121 ► 



SOFTWARE SUL CD T ■ Librerie e Tool di sviluppo 



sistema che consente di scrivere tramite 
un editor html online delle pagine web 
molto semplici, la particolarità sta nel fatto 
che se in una pagina è contenuta una paro- 
la del tipo "DocumentazioneStorica" per 
esempio, cioè spezzata con le lettere maiu- 
scole, verrà automaticamente creata una 
nuova pagina avente come titolo le due 
parole ricongiunte, il link verrà posiziona- 
to nella pagina originale e sarà possibile 
editare la seconda pagina con un sistema 
ad albero, inoltre ogni qualvolta in una pa- 
gina verrà inserita la parola originale, auto- 
maticamente verrà creato un link. La se- 
conda particolarità di un wiki è che nor- 
malmente viene utilizzato come forma di 
scrittura collaborativa, ovvero gli utenti 
autorizzati possono apportare delle modi- 
fiche alle pagine, creando una sorta di revi- 
sione. Per tutti questi motivi i Wiki sono 
molto utilizzati per la creazione rapida di 
documentazione. 
Directory /tikiwiki 

Zope 2.7 

L'application server basato su Python 

Molti di voi saranno abituati a sviluppare 
pagine Web utilizzando PHR ASRNET e al- 
cuni JSP. Altri addirittura utilizzeranno 
Perl, eppure è possibile sviluppare per il 
web utilizzando Python. Questo tipo di svi- 



luppo comporta una serie di vantaggi co- 
me quello di avere a disposizione un lin- 
guaggio multipiattaforma, object oriented, 
molto elegante e flessibile, inoltrre python 
si sta sempre di più affermando come lin- 
guaggio di scripting base per la gestione 
dei sistemi operativo. Linux in quasi tutte 
le distrubuzioni ha almeno uno script di 
gestione basato su Python, ma molte di- 
stribuzioni ne fanno addirittura l'asse por- 
tante. Anche in ambiente Windows Python 
si sta diffondendo rapidamente, così sce- 
gliere di adottare questo linguaggio anche 
per lo sviluppo di applicazioni Web può 
rappresentare una scelta di continuità. 
Directory: /Zope 

MySQL Connector 

Per utilizzare MySQL direttamente 
da applicazioni .NET, Java, Python 

MySQL sta rapidamente diventando uno 
standard. Se fino a ieri lo standard per le 
applicazioni sviluppate in ambienti Micro- 
soft era MS SQL Server, rapidamente a 
questo prodotto si sta affiancando proprio 
MySQL. Allo stesso modo MySQL sta di- 
ventando uno standard per Java e persino 
per Python. Tutto quello di cui avete biso- 
gno per utilizzare MySQL in modo nativo 
direttamente da uno di questi ambienti è 
un "Connector" che fornisca al linguaggio 



il layer per la connessione e la gestione. In 
questo numero trovate tutti i connector di 
cui avete bisogno. 
Directory: /Connector 

Lua 

Per dotare i propri programmi 
di un ambiente di scripting 

Non è inusuale che i software commerciali 
siano dotati della possibilità di essere este- 
si tramite un linguaggio di scripting pro- 
prietario. 




Tipicamente per dotare i propri software di 
questa funzione, è necessario programma- 
re un intero motore di scripting, in alterna- 
tiva si può integrarvi all'interno un engine 
già pronto come ad esempio LUA. Ci parla 
diffusamente di questa tecnica Alfredo 
Marroccelli nell'articolo proposto in que- 
sto stesso numero di ioProgrammo. 



PLOME 2.0 



Un cms atipico 

Dice bene il sottotitolo "un 
cms atipico". Pione oltre a 
essere un CMS piuttosto 
potente dotato di tutte le 
normali carattaristiche di 



un CMS oltre che di funzio- 
nalità di file sharing di 
wiki di editing tali che lo 
rendono particolarmente 
indicato non solo per esse- 



re utilizzato come portale 
web ma anche e soprattut- 
to in ambiti di intranet. 
Questa sua particolare 
vocazione è data anche dal 
fatto di basarsi su Zope 
l'Application Server svilup- 
pato interamente in Py- 
thon decisamente indicato 



per la gestione delle docu- 
mentazione in ambiti di in- 
tranet. 

Questa è anche la partico- 
larità di Pione, ovvero la 
sua robustezza dovuta al 
fatto di essere basato su 
Zope. 

Directory /Pione 



PUBBLICARE CON PLOME 



©*«. . o aie p<~ a» e a- a ■ • ; j e m -a 




SCEGLIAMO IL TIPO DI DOCUMEN- 
i TO - Fra quelli disponibili indivi- 
duiamo quale tipo di pubblicazione 
desideriamo effettuare 



COMPILIAMO I DATI - Nella pagina 
■ successiva inseriamo tutti i dati 
necessari per la pubblicazione 



■ PHff.1. 1 


ioPiogrammo presenta Pione >a»a 


ffiMSK' 




S^S5S£S£^Sir 



H PUBBLICATO - Il documento verrà 
pubblicato online con modalità 
che dipendono dai ruoli di chi ha inseri- 
to il documento 



► 122 /Aprile 2005 



http://www.ioprogrammo.it 



Librerie e Tool di sviluppo ■ T SOFTWARE SUL CD 



ULTÌMATE++ 

Un fantastico ide "quasi RAD" per le applicazioni C++ 



Si tratta di un ambiente di 
sviluppo per applicazioni 
C++, nella versione 
allegata a ioProgrammo. 



Lo trovate abbinato al 
compilatore Mingw; 
nonostante questo può 
essere utilizzato anche con 



altri compilatori. 
L'ambiente offre tutte le 
caratteristiche classiche di 
un ambiente professionale, 
parliamo di code 
complexion, debugging, 
sintax highlighting. 
La caratteristica più 



interessante dell'IDE è che 
è dotato di un minimo di 
funzionalità RAD il che 
dato i bassi costi del 
pacchetto lo rende 
particolarmente attraente 
agli occhi degli 
sviluppatori. 



as 


Aisemhiu 




MyÀppj' 

r 




New OK | Cancel 



Q CREIAMO UN NUOVO PROGETTO - 
Dopo averlo lanciato Ultimate++ ci 
chiede cosa vogliamo fare. Nel mostro 
caso sceglieremo MyApps e poi new per 
dire che vogliamo creare un'applicazio- 
ne personalizzata. 




□ IMPOSTIAMO LA LABEL - Nella 
colonna centrale scegliamo "Set 
label" e digitiamo l'etichetta che voglia- 
mo venga mostrata sulla form. 
Aiutiamoci con il mouse per posizionare 
la label. 




B IMPOSTIAMO LE CARATTERISTICHE 
- Scegliamo il nome dell'applica- 
zione e la sua posizione sull'Hard Disk, 
ma soprattutto indichianmo che voglia- 
mo che la nostra applicazione sia dotata 
di un layout. 



^r 



i IliTa I (51 2, 384): 



vel f?ùii 3 I 7 BLITZ 



' ,1 1 , ,. ' «J. 


pò* | 




el |Hone _*| R BLITZ 








Blitz 








Cu» b 






DrICore 






i. ,1 


















Core 



























H SCEGLIAMO IL COMPILATORE - 
Clicchiamo sulla finestrelle che 
indica il compilatore nella barra del 
menu per scegliere a quale strumento 
vogliamo affidare la compilazione del- 
l'applicazione. 




Userete 




Editors ► 


^H^^bV2 




Ali * ™ LabelBox 



HDISEGNAMO L'INTERFACCIA - 
Selezioniamo il componente di 
tipo "lay" nella colonna di sinistra. 
Verrà mostrata la form che compone 
l'applicazione. Cliccando con il tasto 
destro del mouse inseriamo una label. 




Q COMPILIAMO - Usiamo il tasto F7 
per lanciare la compilazione oppu- 
re scegliamo "Build" dall'omonimo 
menu. L'eseguibile sarà disponibile in 
una directory accessibile come "Output 
directory". 



All'interno della directory oltre ai file ne- 
cessari per eseguire la tecnica trovate an- 
che Lualde, ovvero un comodo IDE pro- 
prio per la creazione di script basati su 
LUA. 
Directory: /Lua 

Sphinx4 

II motore di riconoscimento vocale 

In questo numero di ioProgrammo trovate 
un articolo completo su come costruire 
un'applicazione a comando vocale. Il mo- 
tore vocale che fa girare questo tipo di ap- 
plicazione è proprio Sphinx4. Interamente 
scritto in Java rappresenta un motore ad 
elevate prestazioni, riesce a riconoscere un 



numero elevato di parole anche in un 
discorso senza interruzioni. 
Leggete l'articolo e scoprirete immediata- 
mente tutte le potenzialità di Sphinx4 
Directory: /Sphinx4 

PHP-GTK 

Creare GUI con PHP 

Chi lo dice che PHP è solo un linguaggio 
di scripting per il Web? Sì certo è usato 
prevalentemente per creare script lato 
server tesi a fare funzionare delle web 
application. È anche vero che è possibi- 
le utilizzare PHP per creare potenti 
script anche lato server. PHP-GTK è un 
layer che consente di utilizzare i widget 



di GTK+ per costruire delle GUI piutto- 
sto potenti da utilizzare in script com- 
pletamente Standalone. 
Directory: /PHP-GTK 

MySQL Administrator 

Il front-end per amministrare 
mysql in modo grafico 

La grande diffusione di MySql degli ultimi 
tempi è avvenuta anche grazie al prolife- 
rare di interfacce grafiche che aiutano 
l'utente nella sua amministrazione ordi- 
naria. È il caso di MySQL Administrator 
che fornisce all'utente un potente, com- 
pleto quanto comodo sistema per la ge- 
stione di ogni aspetto di mySQL. Si parte 



http://www.ioprogrammo.it 



Aprile 2005/ 123 ► 



SOFTWARE SUL CD T 



Librerie e Tool di sviluppo 



dalla creazione degli utenti fino alla ge- 
stione dei permessi, alla creazione dei da- 
tabase, alle statistiche sull'uso del server. 
Directory: /mysql-administrator 

MyODBC 

Il connector universale per MySQL 

Se volete sviluppare un'applicazione che 
faccia uso di MySQL ma non disponete di 
un connector nativo, è gioco-forza fare 
uso di MyODBC. Vero è che ormai esisto- 
no connector per qualsiasi tipo di lin- 
guaggio. Quasi tutto quello che serve lo 
trovate allegato a questo numero di io- 
Programmo, altrettanto vero è che ci so- 
no dei casi in cui è ancora opportuno uti- 
lizzare MyODBC. Il caso più tipico è quel- 
lo delle pagine ASP, se disponete di un 
sito scritto in ASP e volete farlo interagire 



con MySQL non potete fare a meno di 
utilizzare MyODBC. 
Directory: /MyODBC 

MySQL Query Browser 

L'editor SQL per MySQL 

Anche in questo caso si tratta di un editor 
visuale. Attenzione non RAD ma semplice- 
mente visuale. Le query vengono costruite 
in parte in modo manuale in parte è possi- 
bile utilizzare dei selettori sotto forma di 
bottoni che aiutano a sviluppare query sin- 
taticamente corrette. MySQL Query Brow- 
ser è un tool che può aiutare in tutte quelle 
situazioni dove è necessario costruire 
query complesse che devono essere salva- 
te, riviste, rieditate più di una volta prima 
di arrivare a un risultato soddisfacente. 
Directory: /mysql-query-browser 



LAZARUS 0.9.4 

Un ambiente RAD più compilatore Freeware per object Pascal 



Volevate imparare a programmare in 
Delphi ma non avevate la possibilità 




IL PRIMO PASSO - Inizialmente 
lazarus si presenta in maniera 
molto simile a Delphi. Con la barra dei 
componenti, la palette delle proprietà 
a sinistra e la form al centro che aspet- 
ta di essere riempita. 



di comperare il costoso ambiente di 
casa Borland? Lazarus è ciò che fa per 
voi. Si tratta di un clone Freeware del 
noto Delphi. La somiglianza è incredi- 
bile! Il modo di procedere altrettanto! 
Lazarus è un RAD funziona con la stes- 
sa logica di Delphi, supporta la VCL, è 
dotato di tutti i componenti classici di 
Delphi, è sufficientemente veloce e 
affidabile. Certo, non è il Borland 
Delphi 2005 con tutte le sue infinite 
possibilità, ma rappresenta un'ottima 
base per chi vuole sviluppare applica- 
zioni Standalone utilizzando la produt- 
tività classica di un ambiente RAD 
come quelli famosi di casa Borland. Si 
tratta di un tool eccezionale che non 
mancherete di iniziare ad apprezzare 
per tutte le sue caratteristiche. 

Directory /Lazarus 



{Smode olij£ B c}{SH+} 



inter 
















Std 
































L 


Left: 323 Top: 2-12 


















{ 




Butt0nl 

























mnp 



POSIZIONARE I COMPONENTI - 
Trasciniamo sulla form una com- 
ponente di tipo label e uno di tipo but- 
ton, possiamo scegliere di ridimensio- 
narli e posizionarli utilizzando le mani- 
glie laterali e il mouse. 



AGGIUNGERE IL CODICE - 
Clicchiamo due volte sul bottone 
per editare l'evento onClick è aggiun- 
giamo il codice come in figura. 
Avviamo l'applicazione usando il pul- 
santino verde in alto a destra. 



Spe 0.7.0 

Un editor evoluto per Pyhton 

La popolarità di un linguaggio si evince an- 
che dal numero di tool e di librerie che 
vengono prodotte a suo supporto. Se dal 
punto di viste delle librerie Python può 
vantare un conspicuo numero di prodotti 
che ne estendono le caratteristiche, dal 
punto di vista invece dei tool ancora non 
avevamo visto degli editor sufficientemen- 
te evoluti da poter supportare pienamente 
lo sviluppo con Python. Spe colma questa 
lacuna. Si tratta di un editor decisamente 
evoluto completo di code completion e di 
sintax highlighting oltre che di tutte le 
caratteristiche tipiche di un editor profes- 
sionale. Sia che stiate imparando a pro- 
grammare in Python sia che siate dei pro- 
grammatori abituali, sicuramente Spe rap- 
presenta un'ottima scelta. 
Directory: /Spe 

Tortoise CVS 

Ottimo tool per il controllo 
della revisione 

Se lavorate in progetti collaborativi o 
semplicemente vi interessa tenere trac- 
cia delle modifiche che fate nel tempo al 
vostro codice, sicuramente saprete cosa è 
un CVS. Tortoise è uno dei frontend più 
utilizzati per la connessione, gestione e 
utilizzo di progetti che fanno uso di un 
server CVS per la tracciabilità delle revi- 
sioni. 
Directory: /tortoisecvs 

Mantaray 

Un completo sistema distribuito 
per la messaggistica aziendale 

Anche in questo caso allegato alla rivista 
trovate un articolo che mostra in detta- 
glio come utilizzare Mantaray. In partico- 
lare Mantaray sfrutta JMS, Java Messa- 
ging Service per la gestione e lo smista- 
mento di messaggi. 

La particolarità risiede nel fatto che il tool 
prevede un'architettura completamente 
distribuita. 
mantaray_1 .2. 1_bin.zip 

Phpmq 

Integra JMS in applicazioni PHP 

PHPMQ sfrutta l'architettura di Manta- 
ray per estendere il meccanismo di Java 
Messaging Service anche ad applicazio- 
ni PHP. Se avrete la pazienza di leggere 
l'articolo all'interno della rivista. Sco- 
prirete come questa possibilità possa ri- 



► 124 /Aprile 2005 



http://www.ioprogrammo.it 



Librerie e Tool di sviluppo ■ T SOFTWARE SUL CD 



DEV C++ 

Un editor C++ a basso costo 



Dev C++ è un editor distri- 
buito su licenza GPL, come 
tale non ha costi relativi al 
diritto d'autore. Come tutto 



o quasi tutto il software GPL 
la sua economicità non è 
affatto sinonimo di scarsa 
qualità. Al contrarilo Dev 



C++ è uno degli editori più 
amati ed utilizzati da chi svi- 
luppa in C++. Le caratteristi- 
che sono notevoli. Si va dal 
Debugger integrato, al 
project Manager, al Class 
Browser, al Code 
Completion. L'insieme di 



queste caratteristiche, oltre 
una leggerezza innata del- 
l'ambiente lo rende partico- 
larmente comodo da utiliz- 
zare per sviluppare progetti 
C++ anche di grandi dimen- 
sioni 

Directory: /Devc++ 



BBS e §]<g 2) 

f] Inserì Roggie j Goto | 



I IEES 

C 



a # a 



L" - . ■_ I IL. IO! 



Project 



r C Project • Dh Projed 

Mài- : [lei-: ! rjage 



• Dk | X Cancel | 7 Help | 



:gin 

MEHUITEM "SCndo", IDM_EDITUNDO 

MEHUITEM SEPAHATOR 

MEHUITEM "SCut\tShÌft+Del", IDM_EDITCUT 



| C^ Debug | @L Find Results | 41 Close | 

v; essane 



[WarningJ uannol ìind snlry symbol JViriMainCRTSlaftup. deiaJjrig fu 00401000 



Q CREIAMO UN NUOVO PROGETTO - 
Sceg I iamo " Windows Application " 
e assegnamo un nome al progetto. 
Dev-C++ creerà per noi lo scheletro del- 
l'aplicazione 



#include <windows.h> 



#include "main.h" 



[...] 



WNDCLASSEX wincl; /* Data structure for 

the windowclass */ 

HMENU menu; 

LJ 

menu = LoadMenu(hThisInstance, 
MAKEINTRESOURCE(ID_MENU)); 



SetMenu(hwnd, menu); 



□ MODIFICHIAMO LO SCHELETRO - È 
arrivato il momento di richiamare 
il menu all'interno dell'applicazione e 
associarlo a una finestra, è esattemente 
quello che facciamo qui 



#include <windows.h> 



#include "main.h" 


501 MENU 


BEGIN 


POPUP "&File" 


BEGIN 


MENUITEM "&New", 


IDM_FILENEW 


MENUITEM "&Open. 


.", IDM_FILEOPEN 


MENUITEM "&Save" 


, IDM_FILESAVE 


MENUITEM "Save &as. 


.", IDM_FILESAVEAS 



MENUITEM SEPARATOR 

MENUITEM "&Print...", IDM_FILEPRINT 
MENUITEM "Page se&tup...", 

IDM_FILEPAGESETUP 

MENUITEM "P&rinter setup...", 

IDM_FILEPRINTSETUP 

MENUITEM SEPARATOR 

MENUITEM "E&xit", IDM_FILEEXIT 
END 

END 



B CREIAMO UN FILE DI RISORSE - 
Scegliere il menu File/New/ 
Resource file. Salveremo il tutto con il 
nome menu.rc. In questo file abbiamo 
definito l'aspetto grafico del menu. 




H AVVIAMO IL TUTTO - Dal menu 
Execute scegliamo "compile ed 
execute" per dare il via alla 
compilazione e all'esecuzione del 
progetto 



#define 


ID_MENU 501 




#define 


IDM_ 


_FILENEW 


200 


#define 


IDM_ 


_FILEOPEN 


201 


#define 


IDM_ 


_FILESAVE 


202 


#define IDM_ 


_FILESAVEAS 


203 


#define 


IDM_ 


_FILEPRINT 


204 


#define 


IDM_ 


_FILEPAGESETUP 205 


#define 


IDM_ 


_FILEPRINTSETUP 206 


#define 


IDM_ 


_FILEEXIT 


207 


EV DEFIAMO GLI ID - A ogni voce 
mM di menu deve essere associata 



una costante numerica. 
Eseguiremo questa associazione in 
un file main.h 



B 


De; 


■ Windows App 






1 

ir 
i 

t. 

□! 

Aqu; 
Stuc 


New 
Open,,, 
Save 
Save as... 




Page setup,,, 
Printer setup,,, 


Exit 







Q OSSERVIAMO I RISULTATI - Se tutto 
è andato a buon fine otterremo 
un risultato come quello in figura, con il 
nostro nuovo menu pronto per essere 
utilizzato 



velarsi piuttosto interessante nella crea- 
zione di intranet aziendali. 
mantaray 1.2.1 bin. zip 

SevenZip 4.10 

Uno dei programmi con migliore 
algoritmo di compressione per file 

Dotato ovviamente di sorgenti, Seven- 



zip ha davvero un altissimo rapporto di 
compressione. Il fatto che i sorgenti sia- 
no disponibili e il programma basato su 
LPGL lo rende particolarmente interes- 
sante e adatto a essere studiato. 
Non di meno utilizzare Seven ZIP porta 
sicuramente dei vantaggi. Supporta 
moltissimi tipi di file fra cui: 7z, ZIP, 



CAB, RAR, ARJ, GZIP, BZIP2, TAR, CPIO, 
RPM e DEB. 

Si integra perfettamente con la shell di 
Windows, è localizzato in 46 linguaggi 
ed ha una versione a linea di comando 
che lo rende adatto a essere usato per 
creare dei file batch. 
Directory: /sevenzip 



http://www.ioprogrammo.it 



Aprile 2005/ 125 ► 



SOLUZIONI T ■ Comprendere gli algoritmi di scheduling 



Analisi di algoritmi di scheduling 



Il Kernel 
ai raggi X 

Il kernel è lo strato più vicino alla macchina, si occupa di compiti 
di cruciale importanza nella gestione del SO. Impariamo come 
il tempo viene diviso fra le varie applicazioni 




Utilizza questo spazio per 
le tue annotazioni 



Conosciamo gli scopi di un SO (sistema opera- 
tivo) e i principali compiti che assolve. Ci sia- 
mo, nello scorso appuntamento, soffermati 
sul ruolo e funzionamento dei processi. Abbiamo 
capito come questi ultimi ricoprano la parte da pro- 
tagonista nella gestione della CPU, e come tale ge- 
stione, che un SO è chiamato ad assolvere, sia di no- 
tevole rilevanza per sistemi multiprogrammati. Si è 
osservato come "concedere" a più processi che ne 
fanno richiesta, il più importante hardware, che non 
a caso è indicato come il "cuore del computer", ossia 
la CPU, sia una mansione niente affatto banale. Il 
compito diventa ancora più arduo se come siamo 
abituati a fare dobbiamo rispettare parametri di 
"buon" funzionamento dell'intero sistema. Si sono 
così ideati molti algoritmi che prevedono la conces- 
sione della CPU (risorsa non divisibile ma comun- 
que interrompibile) rispettando diversi parametri di 
ottimizzazione. Si tratta degli algoritmi di schedu- 
ling. I due fondamentali algoritmi di scheduling il 
FCFS (first come first served) e SJF (shortest job first) 
sono stati esaminati per primi. Si tratta di due meto- 
di event driven, in cui l'assegnazione della CPU av- 
viene in funzione del verificarsi di alcuni eventi e il 
processo deterrà la preziosa risorsa CPU fin quando 
non avrà terminato il suo lavoro. Nel panorama, a 




PU E MEMORIA 



La CPU e la memoria 
rappresentano le più 
importanti risorse di 
cui dispone un elabo- 
ratore. In ambiente 
multiprogrammato 
hanno però caratteri- 
stiche differenti. 
Mentre la prima non 
è divisibile, la memo- 



ria può essere parti- 
zionata in più parti 
da assegnare contem- 
poraneamente a 
diversi processi che 
ne fanno richiesta. La 
CPU, però, si può 
interrompere nella 
sua attività e quindi 
essere "concessa" a 



più processi solo in 
diversi tempi. La con- 
temporaneità di ese- 
cuzione di più task è 
pertanto solo un'im- 
pressione che deriva 
dalla concessione 
molto veloce a più 
processi per fissati 
intervalli di tempo. 



dire il vero molto ricco, delineato da tutti gli algorit- 
mi rimane da studiare un altro del tipo event driven, 
a priorità; un algoritmo che segue la logica time dri- 
ven, il round robin, e infine un metodo misto a coda 
multilivello. Per il primo dei metodi indicati appron- 
teremo un'analisi dettagliata seguita da simulazione 
attraverso la produzione di un programma C++. 
I restanti saranno accennati e forse sviscerati in fu- 
turo. Infine, verrà descritta una comparazione tra i 
metodi. 



ALGORITMO A PRIORITÀ 

Il metodo FCFS nello scegliere tra i processi disposti 
nella coda di ready, (pronti a essere eseguiti -run) se- 
gue una logica FIFO, quindi dalla lista dei processi 
estrae il più "anziano", ossia quello che da più tempo 
attende. SJF invece, sceglie il processo che ha una 
minore richiesta di tempo; in tal modo si garantisce 
un buon tempo turnaround medio (ricircolo), ossia 
mediamente i vari processi dovranno attendere me- 
no rispetto al caso precedente. Il limite di SJF è l'im- 
possibilità di conoscere il tempo richiesto di CPU 
dai singoli processi, che può essere solo stimato, con 
prevedibili errori a volte rilevanti. Una soluzione 
sempre più usata fa uso di priorità. Ad ogni proces- 
so viene assegnata una priorità, ossia un numero 
compreso in un intervallo. Range usati sono [0, 7] e 
[0, 4095]. Tra i processi pronti ad essere eseguiti si 
sceglie quello a priorità maggiore, che ha il numero 
più grande. Alcuni algoritmi considerano come pro- 
cessi ad alta priorità quelli che hanno numeri vicini 
allo zero. Questo è un sistema molto più flessibile 
dei precedenti, poiché la priorità può essere espres- 
sa in funzione di molti parametri. Ad esempio, se si 
produce il livello di priorità in funzione della sola sti- 
ma del tempo richiesto da un singolo processo, allo- 
ra, evidentemente il metodo "degenera" nel SJF. Ma 



^ 126 /Aprile 2005 



http://www.ioprogrammo.it 



Comprendere gli algoritmi di scheduling ■ T SOLUZIONI 



nel caso più generale la prelazione si può ottenere in 
funzione di molti fattori, che possono essere stabili- 
ti in parte anche dall'utente che produce il processo 
il quale può fissare un valore di partenza. In genera- 
le i fattori che contribuiscono sono: le richieste di 
risorse, il comportamento del processo in esecuzio- 
ne, il tipo di processo (qualora il SO sia in grado di 
effettuare una classificazione) e comunque eventi 
esterni. Ad ogni modo, non è molto rilevante il come 
si produca la priorità, a mio avviso è utile sapere che 
esiste questo utile strumento che può essere anche 
configurato dal sistemista. Prima di passare alla si- 
mulazione del sistema osserviamo dei possibili ri- 
schi di cui potrebbe soffrire il metodo. Ad esempio, 
processi a bassa priorità, nel caso in cui le code di 
ready siano regolarmente "affollate", potrebbero ri- 
schiare di essere eseguiti molto "tardi" non garan- 
tendo tempi di risposta minimi spesso imposti co- 
me specifiche di sistema (tipici dei SO real time). Per 
il problema specifico si è trovata una soluzione che 
permette di servire il processo in questione aggiun- 
gendo alle componenti che contribuiscono alla de- 
terminazione della priorità anche l'anzianità cono- 
sciuta in gergo come aging priority. 



IL CODICE 

Il programma riportato di seguito vuole essere una 
semplice simulazione di un algoritmo a priorità. Per 
rendere il tutto più semplice e comprensibile alcuni 
eventi che nella realtà avvengono in seguito ad inter- 
rupt, solitamente gestiti mediante programmazione 
concorrente, nel caso specifico sono simulati me- 
diante input manuali da console. Anche le strutture 
dati sono semplificate per focalizzare l'attenzione 
sulle dinamiche che muovono le scelte dell'algorit- 
mo di priorità, per cui anziché trattare un PCB nella 
sua completezza avremo a che fare con una struttu- 
ra che contiene le informazioni salienti di un pro- 
cesso, identica cosa dicasi per le altre strutture come 
i tracciati dei log. Eventuali altre scelte saranno 
esposte in fase di commento del codice prodotto. Il 
programma proposto è nella sua versione integrale. 
La prima parte riporta ovviamente la struttura dati 
espressa come una serie di variabili semplici e strut- 
turate entrambe globali, visibili quindi all'intero am- 
bito del programma. 

// simulp.cpp 

// Semplice programma per la simulazione del 

// metodo priorità per l'assegnazione della CPU 

// ai processi in stato di ready. 



// valutazione di alcuni parametri. 



#include<iostream.h> 



#include<string.h> 



// numero massimo di processi 



// numero massimo di azioni (ass. CPU) 

const int nmaxlog = 200; 

// stima tempo medio di sistema tra una ass. e la succ. 

const int tsys=l; 



// tempo attuale 



int t=0; 



// numero corrente di log 



int nlog=-l; 



// informazioni salienti circa un singolo processo 
// in stato di coda di ready 



struct tprocesso 



{ char nome[8]; 



int num, prior, tp; 



} processo; 



// coda di processi in ready 



tprocesso coda[nmaxproc]; 



// situazione sommativa del sistema 



// numero di processi, tempo utente totale utilizzato 
// tempo sistema totale utilizzato, tempo inattività 
struct tsistema 



{ int np, tu, ts, ti; 



} sistema; 



// traccia delle attività di CPU 



struct tlog 



{ tprocesso proc; 



int tiniz, tfine; 



const int nmaxproc=100; 



} logs[nmaxlog]; 

Le prime due costanti descrivono le dimensioni di 
due array molto importanti; nmaproc e nmaxlog 
corrispondono ai vettori coda e logs. I due array ten- 
gono traccia rispettivamente: dei processi che sono 
in coda di ready che verranno opportunamente or- 
dinati in base alla loro priorità e a tutte le attività del- 
la CPU per fissate unità di tempo. Esaminando i tipi 
base che costituiscono tali vettori si comprende me- 
glio il ruolo che ricoprono, tprocesso è un tipo strut- 
tura (un record) che contiene le informazioni di un 
singolo processo, dal nome al suo numero d'ordine, 
e anche la priorità e il tempo richiesto di CPU. Serve 
una precisazione che proietti la realtà al tipo di si- 
mulazione che ho approntato. La priorità sarà un 
valore numerico compreso nell'intervallo [0, 4095] 
inserito manualmente, ma che, come nella realtà 
può essere modificato (infatti, la priorità di un pro- 
cesso può variare nel tempo di vita del processo 
stesso). Il tempo di CPU richiesto va visto come l'ef- 
fettiva tempo di utilizzo della risorsa e non come 
una stima. Il fatto che verrà inserito in fase di produ- 
zione dell'array coda risponde soltanto ad un'esi- 
genza di comodità. La struct sistema contiene infor- 
mazioni generali sull'andamento della CPU: il nu- 
mero di processi in attesa e i vari tempi di utilizzo. I 
tempi sono: utente come somma degli usi dei vari 
processi; sistema come tempo impiegato dal SO tra 
una assegnazione e l'altra di CPU per l'elaborazione 
della scelta (per semplicità si è considerato fisso, di 
una sola unità di tempo). Un'unità assume il valore 




EVOLUZIONE 
DI MLS 

MLQ con feedback è 
una evoluzione del 
sistema a code 
multiple. Qui un job 
non è fisso in una coda 
ma può spostarsi in 
funzione delle attività 
generali di sistema da 
una coda ad un'altra. 



http://www.ioprogrammo.it 



Aprile 2005/ 127 ► 



SOLUZIONI T ■ Comprendere gli algoritmi di scheduling 




COMPILATORE 
USATO 

Il compilatore usato è 

Dev-CPP di bloodshed 

nella versione 4.2. 

Un interessante 

compilatore free dalle 

potenzialità davvero 

sorprendenti. 



che l'utente trova più opportuno assegnarli, può es- 
sere facilmente traslata rispetto al microprocessore 
in uso; può valere un decimo di micro secondo co- 
me un nano secondo. Le variabili globali usate sono 
t che indica il tempo corrente, nlogìa. quantità attua- 
le di log, ovvero il numero della generica (corrente) 
attività della CPU. 

Cominciamo con l'esaminare le funzioni di servizio 
per la configurazione delle variabili e per l'output. 

// funzione di inizializzazione 

void setupQ 

{ 



int i; 



t=0; 



nlog=0; 



sistema. tu =0; 



sistema. ti =0; 



sistema. ts=0; 



cout<<"n. processi iniziali 



cin>>sistema.np; 



for (i=0; i<sistema.np; i++) 



{ coda[i].num = 



cout<<"nome processo -> "; 



cin>>coda[i].nome; 



cout<<"priorità (0 - min , 4095 max) -> "; 



cin>>coda[i].prior; 



cout<<"tempo richiesto -> "; 



cin>>coda[i].tp; 



±_ 



}; 



// visualizzazione dello stato generale del sistema 
void visualsysQ 



{ cout<<"\n situazione attuale di sistema \n" 
<<" n. processi attivi : "<<sistema.np 



<<"\n tempo utente totale utilizzato :"<<sistema.tu 
<<"\n tempo sistema totale utilizzato 

:"<<sistema.ts<<'\n'; 



}; 



// visualizzazione della coda di ready 



void visualcodaQ 



{ int i 



cout<<"\n situazione attuale della coda di ready \n" 
for (i=0; i<sistema.np; i++) 



{ cout<<"\n "<<i<<" - processo( 

"<<coda[i].num<<"): " 
<<coda[i].nome<<" / priorità: "<<coda[i].prior 
<<", tempo richiesto: "<<coda[i].tp; 



}}; 



// Output del log 



void visuallogQ 



{ int i 



cout<<"\n Storia dell'attività di CPU \n"; 



cout<<"nome"<<"\t\t" 



<<"n."<<'\t' 



<<"tempo"<<'\t' 



<<"prior"<<'\t' 



<<"t.iniz"<<'\t' 



<<"t.fine"<<'\n'j 





for 


(i=0; i< = nlog; i + + ) 




{ 


cout<<'\n'<<logs[i].proc.nome<<"\t\t" 


<<logs[i].proc.num<<'\t' 


<<logs[i].proc.tp<<'\t' 


<<logs[i].proc.prior<<'\t' 


<<logs[i].tiniz<<'\t' 


<<logs[i].tfine<<'\n'; 


} 


}; 



Con setup vengono inizializzate tutte le variabili pri- 
ma descritte. Inoltre, vengono inseriti i primi pro- 
cessi. Naturalmente è possibile aggiungerne in itine- 
re, durante la normale attività della CPU. La famiglia 
delle funzioni visual produce l'output dei dati sensi- 
bili quali il vettore logs e il vettore coda contenente le 
informazioni sui vari processi. Durante l'attività di 
sistema si possono aggiungere nuovi processi che 
quindi arricchiscono la coda di ready; alcuni di essi 
possono variare delle informazioni come ad esem- 
pio la priorità. Le due attività sono svolte dalle due 
routine riportate di seguito aggiuntaQ e aggiornai). 
Contestualmente viene aggiornato il record sistema. 

// eventuale aggiunta di nuovi processi 



void aggiuntaQ 



{ intj,npagg; 



cout<<"\n n. processi da aggiungere (0 - esci) -> "; 
cin>>npagg; 



for (j=0; j<npagg; j++) 



{ coda[j+sistema.np].num=j+sistema.np; 



cout<<"nome processo -> "; 



cin>>coda[j+sistema.np].nome; 



cout<<"priorità (0 - min , 4095 max) -> "; 



cin>>coda[j+sistema.np].prior; 



cout<<"tempo richiesto -> "; 



cin>>coda[j+sistema.np].tp; }; 



sistema.np+ = npagg; } 



// aggiorna la richista di tempo e/o priorità 



// dei processi in stato di ready 



void aggiornaQ 



{ int npagg.com; 



visualcodaQ; 



cout<<"\n n. processo da aggiornare (-1 esci) -> "; 
cin>>npagg; 



while (npagg!=-l) 



{ cout<<"priorità: "<<coda[npagg].prior 

<<"\n nuova (-1 lascia invariata) -> "; 
cin>>com; 

if (com != -1) coda[npagg].prior=com; 

cout<<"tempo da aggiungere (attuale: 

"<<coda[npagg].tp 

<<") al processo -> "; 

cin>>com; 



coda[npagg].tp+=com; 



cout<<"\n numero di processo da aggiornare ( 
-1 esci)"; 



cin>>npagg; } } 



^ 128 /Aprile 2005 



http://www.ioprogrammo.it 



Comprendere gli algoritmi di scheduling ■ T SOLUZIONI 



Per potere estrarre il processo a maggiore priorità si 
può agire o facendo una ricerca esaustiva, quindi se- 
quenziale, sul vettore coda dei processi, oppure or- 
dinando questo ultimo (ovviamente sulla base del 
campo prior) ed estrarre l'elemento in cima. Sceglia- 
mo la seconda opzione. 



void sort() 


{ 


int i,j; 






tprocesso temp; 




for (1=0; 


i<sistema.np-l; i++] 






for(j: 


=0; j<sistema.np-i-l; 


j++) 




if ( 


coda[j].prior<coda[j+ 


1]. prior) 




{ 


temp=coda[j]; 




coda [j] = coda [j+1]; 


coda[j+l]=temp; } 


}; 



la funzione cruciale assegna la CPU al processo a più 
alta priorità, dopodiché aggiorna opportunamente i 
log e le altre variabili globali. Il codice prodotto è ab- 
bastanza autoesplicativo, diamogli un'occhiata. 

// Assegnazione del processo allo stato di run 

// inoltre aggiorna le strutture coda, sistema e logs 



// nonché la variabile t 



void assegnaQ 



{ 



int i 



// attività di sistema 



sistema.ts+=tsys; 



++nlog; 



strcpy(logs[nlog].proc.nome, "sistema"); 



logs[nlog].proc.tp=tsys; 



logs[nlog].proc.num=-l; 



logs[nlog].proc.prior=-l; 



logs[nlog].tiniz=t; 



logs[nlog].tfine=t+tsys; 



t+=tsys; 



// si preleva in cima alla lista 



// processo a maggiore priorità 



++nlog; 



strcpy(logs[nlog].proc.nome,coda[Q].nome); 



logs[nlog].proc.tp=coda[0].tp; 



logs[nlog].proc.num=coda[0].num; 



logs[nlog].proc.prior=coda[0] .prior; 



logs[nlog].tiniz=t; 



logs[nlog].tfine=t+coda[Q].tp; 



t+=coda[0].tp; 



sistema.tu+=coda[0].tp; 



// traslazione della restante parte di coda 



for (i=l; i<sistema.np; i++) 



{ coda[i-l]=coda[i]; }; 



// aggiornamento generale 



sistema.np- 



}; 



Un possibile main program è riportato di seguito. Il 
ciclo continua fin quando vi sono processi in coda. 



Si potrebbe iterare ulteriormente il processo e pre- 
vedere tempi di inattività. Estendere il codice a tale 
eventualità può risultare un piacevole esercizio. 

// programma principale 

// semplice simulazione 
int main() 




{ setupQ; 



while (sistema.np!=0) 



{ aggiuntaQ; 



sortQ; 



aggiornaQ; 



assegnaQ; 



visualsysQ; 



visualcodaQ; }; 



visuallogQ; 



char quit; 



cin>>quit; 



Fig. 1: Output del programma simulp.cpp 



} 

In Figura 1 si può osser- 
vare in che termini si pro- 
duce l'output. Sono visi- 
bili i vari processi, non- 
ché la parola sistema che 
indica un utilizzo della 
CPU da parte del SO. Di 
seguito sono riportati il 
numero d'ordine del pro- 
cesso, la sua priorità il 
tempo richiesto e gli in- 
tervalli di uso della CPU; 
insomma un log minimo 
per tenere traccia delle 

attività di sistema. Inoltre, sono visibili i tempi totali 
di utilizzo del sistema. Tali dati possono essere usati 
per il calcolo di parametri come throughput e cpu 
activity. 



LOGICA TIME DRIVER! 
E MISTA 

In contrapposizione con una filosofia che tende ad 
"accontentare" le richieste dei singoli processi per 
intero in termini di tempo di utilizzo della CPU, si 
contrappone un metodo che non garantisce ciò. Nei 
metodi lime driver, di cui il round robin ne è la più 
comune espressione, si parte dal presupposto che 
ogni processo non può detenere la CPU per un tem- 
po maggiore di un fissato time slice (fetta di tempo). 
Qualora il time slice non sia sufficiente per soddisfa- 
re le richieste di un processo, questi dovrà essere 
spezzettato in fette di tempo pari al time slice ed 
essere servito in differenti tempi. Un sistema così 
organizzato si dice che sia in time sharing. 
Ne parleremo nei prossimi numeri. 

Fabio Grimaldi 




http://www.ioprogrammo.it 



Aprile 2005/ 129 ►